Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)
龙沙网站制作公司哪家好,找创新互联建站!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设等网站项目制作,到程序开发,运营维护。创新互联建站于2013年成立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联建站。
fork完后:
(1)有两个返回值,子进程返回0,父进程返回子进程的id
(2)父子进程谁先运行不确定,由调度系统说了算,但是期望子进程先退出,并且父进程在子进程退出时读取子进程的状态
(3)代码区域: 打印与循环的关系,例如父子进程各自++,第一次打印2个,第二次由2变4,一共打印6次
Fopen(标准C库函数提供)——返回值是FILE*
FILE* stdin: 输入 输入设备:键盘 默认打开文件的描述符:0
FILE* stdout: 输出 输出设备:显示器 默认打开文件的描述符:1
FILE* stderror: 错误 输入设备:显示器 默认打开文件的描述符:2
open(系统调用提供)——返回值new file descriptor(fd)、-1、error
fwrite(有缓冲区):由C语言提供缓冲区,默认为行缓冲,遇到换行符就刷新,但是当重定向到文件时,变成全缓冲,就不刷新,直到缓冲区写满。fork前:暂存在于父进程缓冲区中不刷新,fork后:父进程复制到子进程,此时将缓冲区也复制过去。当进程终止时再刷新缓冲区
write(无缓冲区)
1。系统调用
系统调用提供的函数如open, close, read, write, ioctl等,需包含头文件unistd.h。以write为例:其函数原型为 size_t write(int fd, const void *buf, size_t nbytes),其操作对象为文件描述符或文件句柄fd(file descriptor),要想写一个文件,必须先以可写权限用open系统调用打开一个文件,获得所打开文件的fd,例如 fd=open(/"/dev/video/", O_RDWR)。fd是一个整型值,每新打开一个文件,所获得的fd为当前最大fd加1。Linux系统默认分配了3个文件描述符值:0- standard input,1-standard output,2-standard error。系统调用通常用于底层文件访问(low-level file access),例如在驱动程序中对设备文件的直接访问。系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性
系统调用发生在内核空间,因此如果在用户空间的一般应用程序中使用系统调用来进行文件操作,会有用户空间到内核空间切换的开销。事实上,即使在用户空间使用库函数来对文件进行操作,因为文件总是存在于存储介质上,因此不管是读写操作,都是对硬件(存储器)的操作,都必然会引起系统调用。也就是说,库函数对文件的操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。这样的话,使用库函数也有系统调用的开销,为什么不直接使用系统调用呢?这是因为,读写文件通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),这时,使用库函数就可以大大减少系统调用的次数。这一结果又缘于缓冲区技术。在用户空间和内核空间,对文件操作都使用了缓冲区,例如用 fwrite写文件,都是先将内容写到用户空间缓冲区,当用户空间缓冲区满或者写操作结束时,才将用户缓冲区的内容写到内核缓冲区,同样的道理,当内核缓冲区满或写结束时才将内核缓冲区内容写到文件对应的硬件媒介。
2。库函数调用
标准C库函数提供的文件操作函数如fopen, fread, fwrite, fclose, fflush, fseek等,需包含头文件stdio.h。以fwrite为例,其函数原型为size_t fwrite(const void *buffer, size_t size, size_t item_num, FILE *pf),其操作对象为文件指针FILE *pf,要想写一个文件,必须先以可写权限用fopen函数打开一个文件,获得所打开文件的FILE结构指针pf,例如pf=fopen(/ "~/proj/filename/", /"w/")。实际上,由于库函数对文件的操作最终是通过系统调用实现的,因此,每打开一个文件所获得的FILE结构指针都有一个内核空间的文件描述符 fd与之对应。同样有相应的预定义的FILE指针:stdin-standard input,stdout-standard output,stderr-standard error。库函数调用通常用于应用程序中对一般文件的访问。库函数调用是系统无关的,因此可移植性好。由于库函数调用是基于C库的,因此也就不可能用于内核空间的驱动程序中对设备的操作。