标准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()的正确用法****************]