Linux System Programming 學習筆記(三) 標準緩衝I/O

1. partial block operations are inefficient.

The operating system has to 「fix up」 your I/O by ensuring that everything occurs on block-aligned boundaries and rounding up to the next largest block安全

 
用戶級程序可能在某一時刻僅僅讀寫一個字節,這是極大的浪費。Each of those one-byte writes is actually writing a whole block
user-buffered I/O:a way for applications to read and write data in whatever amounts feel natural but have the actual I/O occur in units of the filesystem
block size

2. User-buffered I/O

上如代表,只要將執行I/O操做的請求數設置爲物理I/O塊大小的整數倍 就能夠得到很大的性能提高。 Larger multiples will simply result in fewer system calls
使用stat系統調用能夠獲知文件I/O塊大小
 
 1 #include <stdio.h>
 2 
 3 int main(int argc, char* argv[])
 4 {
 5     struct private {
 6         char           name[100];    /* real name */
 7         unsigned long  booty;        /* in pounds sterling */
 8         unsigned int   beard_len;    /* in inches */
 9     };
10     struct private p;
11     struct private blackbeard = {"Edward Teach", 950, 48};
12 
13     FILE* out = fopen("data", "r");
14     if (out == NULL) {
15         fpiintf(stderr, "fopen error\n");
16         return 1;
17     }
18 
19     if (fwrite(&blackbeard, sizeof(struct private), 1, out) == 0) {
20         fprintf(stderr, "fwrite error\n");
21         return 1;
22     }
23 
24     if (fclose(out)) {
25         fprintf(stderr, "fclose error\n");
26         return 1;
27     }
28 
29     FILE* in = fopen("data", "r");
30     if (in == NULL) {
31         fprintf(stderr, "fopen error\n");
32         return 1;
33     }
34     if (fread(&p, sizeof(struct private), 1, in) == 0) {
35         fprintf(stderr, "fread error\n");
36         return 1;
37     }
38 
39     if (fclose(in)) {
40         fprintf(stderr, "fclose error\n");
41         return 1;
42     }
43 
44     fprintf(stdout, "name = \"%s\" booty = %lu beard_len = %u\n", p.name, p.booty, p.beard_len);
45     return 0;
46 }

 

it's important to bear in mind that because of differences in variable sizes, alignment, and so on, binary data written with one application may not be readable by other applications. These things are guaranteed to remain constant only on a particular machine type with a particular ABI
 
fflush() merely writes the user-buffered data out to the kernel buffer. Calling fflush(), followed immediately by fsync(): that is, first ensure that
the  user buffer is written out to the kernel and then ensure that the kernel's buffer is written  out to disk.

 

int fileno (FILE *stream);   //返回文件流(C標準I/O庫)對應的文件描述符(Unix系統調用) 

 

毫不能混用Unix系統調用I/O和C語言標準I/O
You should almost never  intermix file descriptor and stream-based I/O operations
 

3. 控制緩衝

標準I/O提供三種類型緩衝:
(1) 無緩衝:Data is submitted directly to the kernel. 無性能優點,基本不用。標準錯誤默認是無緩衝
(2) 行緩衝: With each newline character, the buffer is submitted to the kernel.  終端文件(標準輸入輸出)默認是行緩衝
(3) 塊緩衝:Buffering is performed on a per-block basis. By default, all streams associated with files are block-buffered
 

4. 線程安全

標準I/O函數自己是線程安全的。標準I/O函數使用鎖機制來確保進程內的多個線程能夠併發執行標準I/O操做。(注意: 確保線程安全的原子區域僅限於單一函數,多個I/O函數之間並不保證)
Any given thread must acquire the lock and become the owning thread before issuing any I/O requests,within the context of single function calls,
standard I/O operations are atomic
 
void flockfile (FILE *stream);
void funlockfile (FILE *stream);
 

5.標準I/O的缺陷

The biggest complaint with standard I/O is the performance impact from the double copy
reading data: kernel ==> standard I/O buffer ==> application buffer 
writing data:  application data ==> standard I/O buffer ==> kernel 
相關文章
相關標籤/搜索