linux自学笔记—标准IO库执行系统内部执行过程和write函数

标准IO库

//fopen,fclose

//fread,fwrite

//fflush

//fseek

//fgetc,getc,getchar

//fputc,put,putchar

//fgets,gets

//printf,fprintf,sprintf

//scanf,fscan,sscanf

//fwrite和write有啥区别;

//fwrite()是标准I/O库一般在stdio.h文件

//write():系统调用;

/有一句话:所有系统调用都是原子性的

标准i/o是要调用系统函数

如:fwrite--调用write

例如:printf()函数不加\n无法及时输出的解释 //printf末尾不加\n就无法及时的将信息显示到屏幕 ,这是因为 行缓存[windows上一般没有,类Unix上才有] //需要输出的数据不直接显示到终端,而是首先缓存到某个地方,当遇到行刷新表指或者该缓存已满的情况下,菜会把缓存的数据显示到终端设备; //ANSI C中定义\n认为是行刷新标记,所以,printf函数没有带\n是不会自动刷新输出流,直至行缓存被填满才显示到屏幕上; //所以大家用printf的时候,注意末尾要用\n; //或者:fflush(stdout);也可以直接刷新 //或者:setvbuf(stdout,NULL,_IONBF,0); //这个函数. 直接将printf缓冲区禁止, printf就直接输出了。


write()函数思考

//多个进程同时去写一个文件,比如5个进程同时往日志文件中写,会不会造成日志文件混乱。

//多个进程同时写 一个日志文件,我们看到输出结果并不混乱,是有序的;我们的日志代码应对多进程往日志文件中写时没有问题;

//《Unix环境高级编程 第三版》第三章:文件I/O里边的3.10-3.12,涉及到了文件共享、原子操作以及函数dup,dup2的讲解;

//第八章:进程控制 里庇安的8.3,涉及到了fork()函数;

//a)多个进程写一个文件,可能会出现数据覆盖,混乱等情况;但如果是父子进程的话不会

//原因:因为是父进程先打开了这个文件fd,子进程都是把fd复制过去的,所以根据文件共享的知识可以保证打印不乱

//b)ngx_log.fd = open((const char *)plogname,O_WRONLY|O_APPEND|O_CREAT,0644); 

  //O_APPEND这个标记能够保证多个进程操作同一个文件时不会相互覆盖;

//c)内核wirte()写入时是原子操作;

//d)父进程fork()子进程是亲缘关系。是会共享文件表项,

//--------------关于write()写的安全问题,是否数据成功被写到磁盘;

//e)write()调用返回时,内核已经将应用程序缓冲区所提供的数据放到了内核缓冲区,但是无法保证数据已经写出到其预定的目的地【磁盘 】;

//内核缓冲区  等待一段时间或许说 一小块满的时候才往磁盘写;注意:写入内核很快,而写入磁盘很慢

//的确,因为write()调用速度极快,可能没有时间完成该项目的工作【实际写磁盘】,所以这个wirte()调用不等价于数据在内核缓冲区和磁盘之间的数据交换

//f)打开文件使用了 O_APPEND,多个进程写日志用write()来写;

//(4.1)掉电导致write()的数据丢失破解法

//a)直接I/O:直接访问物理磁盘:

//O_DIRECT:绕过内核缓冲区。用posix_memalign

//b)open文件时用O_SYNC选项:

//同步选项【把数据直接同步到磁盘】,只针对write函数有效,使每次write()操作等待物理I/O操作的完成;

//具体说,就是将写入内核缓冲区的数据立即写入磁盘,将掉电等问题造成的损失减到最小;

//不管用哪种方法,每次写磁盘数据,务必要大块大块写,一般都512-4k 4k的写;不要每次只写几个字节,否则会被抽死;************

//推荐:c)缓存同步:尽量保证缓存数据和写道磁盘上的数据一致;

//sync(void):将所有修改过的块缓冲区排入写队列;然后返回,并不等待实际写磁盘操作结束,数据是否写入磁盘并没有保证;

//推荐:fsync(int fd):将fd对应的文件的块缓冲区立即写入磁盘,并等待实际写磁盘操作结束返回;*******************************

//fdatasync(int fd):类似于fsync,但只影响文件的数据部分。而fsync不一样,fsync除数据外,还会同步更新文件属性;

//write(4k),1000次之后,一直到把这个write完整[假设整个文件4M]。再调用fsync一次即可

//fsync(fd) ,1次fsync [多次write,每次write建议都4k,然后调用一次fsync(),这才是用fsync()的正确用法****************]

你可能感兴趣的:(linux自学笔记—标准IO库执行系统内部执行过程和write函数)