寫入(write)是由類Unix作業系統內核提供的最為基本的程序。此程序從用戶定義的緩衝中將數據寫入設備或文件,這也是從程序中使用系統調用直接輸出數據的主要方式。待寫入的地點由文件描述符定義;要寫入的數據(如文本)由指針和大小(字節數)定義。

write也因此需要三個參數:

  1. 文件代碼(文件描述符fd)
  2. 指向文件存儲地的緩衝的指針(buf);
  3. 要從緩衝中寫入的字節數(nbytes)。

POSIX用法

寫入調用接口[1][2]根據POSIX規範定義。通過調用寫入函數,數據才能寫入文件。此函數的原型為:

 ssize_t write(int fd, const void *buf, size_t nbytes);
參數 描述
fd
根據調用打開函數獲取的文件描述符。此參數是一個可為0、1或2整數值,其值分別代表了標準輸入、標準輸出和標準錯誤。
buf
指向字符陣列,其內容為fd參數指向的文件。
nbytes
指定從字符陣列寫入fd參數指向的文件的字節數。

在上述語法中,ssize_t是一個typedef(定義於stddef.h中帶符號的數據類型)。但注意write()會在發生錯誤的時候返回-1(參見下方的錯誤一節),故其一定會返回帶符號的值。 寫入函數將返回成功寫入數組的字節數,即意味著有時此值將小於指定的nbytes

使用示例

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main_gg (int argc, char *argv[])
{
    int fd1;
    char buf[128];
    fd1 = open(argv[1], O_WRONLY);
    if (fd1 == -1) {
        perror(argv[1]);
        return EXIT_FAILURE;
    }

    /* 输入待写入至文件的数据 */
    scanf("%127s", buf);

    write(fd1, buf, strlen(buf)); /* fd1为文件描述符,buf为用于存储数据的字符阵列,strlen(buf)用于通知函数缓冲中需要复制的字符串字节长度 */

    close(fd1);

    return 0;
}

操作錯誤

下方列出的是在寫入文件時可能會發生的錯誤[3][4]。這些錯誤為errno.h中列出的宏命令。

錯誤數字 錯誤 意義
4
EINTR
系統調用中斷。
5
EIO
低級錯誤,通常與硬體的讀取/寫入操作有關。
9
EBADF
文件描述符fd無效,或是正嘗試寫入打開為「只讀」模式的文件。
13
EACCES
用戶沒有寫入文件的所需權限。
14
EFAULT
函數中指定的地址無效。
22
EINVAL
函數傳遞的參數無效。
27
EFBIG
指定於nbytes中的文件大小過大,且大於系統所允許的值。
28
ENOSPC
待寫入至的存儲設備上的存儲空間不足。
32
EPIPE
管道損壞,或是在管道另一端的文件不可用於I/O(大多數拋出此錯誤的進程同時會產生SIGPIPE信號)。

調用寫入的高級I/O函數

雖然看起來很像,但寫入系統調用不是一個普通的函數。例如在x86架構上的Linux系統上,此系統調用會使用INT 80H指令以將控制權轉移給內核。[5]寫入系統調用,及其配對函數讀取(read)均是只能理解字節的低級函數。寫入函數不可用於寫入記錄(如)。因此,此時通常需要高級的輸入輸出函數(如printf)。通常與混亂的低級接口相比,程式設計師更偏好使用高級接口。這些函數在內部調用其他函數,反之也可做出寫入調用,進而打造出了分層函數組合。[6]

有了這種組合,高級函數可收集數據的字節並隨後寫入文件。

 
調用寫入的高級I/O函數

參見

  • fwrite
  • getchar
  • fprintf
  • pwrite ()
  • read (system call)
  • sync (Unix)

參考文獻

外部連結