目录一. 系统调用1.1 什么是系统调用二. open/close函数2.1 open函数2.2 close函数2.3 open函数常见的三种错误三. read/write函数3.1 read函数3.2 write函数3.3 使用read与write实现命令cp四.系统调用与库函数的比较4.1 使用fputc与fgetc实现cp命令4.2 预读入缓输出机制一. 系统调用1.1 什么是系统调用是由操作系统实现并提供外部应用程序的编程接口(Application Programming InterfaceAPI)。是应用程序同系统之间数据交互的桥梁。系统调用(内核提供的函数)操作系统的本质的程序代码而操作系统的核心程序叫内核只有系统调用才能进入内核空间例如“hello”如何打印在屏幕上实际上其实write函数并不是真正的系统调用而只是sys_write做了一层浅封装sys_write才是真正的系统调用write可以称其为系统函数。二. open/close函数2.1 open函数函数原型描述函数会打开由路径名指定的文件若文件不存在在某些情况下会创建文件。返回值成功返回一个文件描述符失败返回-1并且设置errno参数flags这些宏在头文件fcntl.h中O_RDONLY只读O_WRONLY只写O_RDWR读写O_APPEND追加O_CREAT不存在则创建O_EXCL是否存在O_TRUNC截断(有数据则清空)O_NONBLOCK非阻塞参数mode(是一个八进制数)创建文件时指定文件的访问权限。权限受umask的影响。结论是文件权限mode ~umaskumask是0002(一个八进制数)eg可得mode取0644文件权限是rw- r-- r--取0664文件权限是rw- rw- ---2.2 close函数函数原型描述关闭打开的一个文件描述符返回值成功返回0 失败返回-1并且设置error2.3 open函数常见的三种错误1、打开的文件不存在2、以写的方式打开只读文件3、以只写的方式打开目录三. read/write函数3.1 read函数函数原型描述从文件描述符fd中读取count字节的数据到缓冲区buf中。返回值成功返回读取的字节数 0表示读到结尾失败返回-1并且设置error。(注意还有另一种情况返回-1且error是EAGAIN或EWOULDBLOCK说明不是read失败而是以非阻塞的方式读一个设备/网络文件且文件里面无数据这个需要另行判断)3.2 write函数函数原型描述从缓冲区buf中最多读取count字节的数据并且写入文件描述符fd中返回值成功返回写入的字节数 0表示没东西可写失败返回-1并且设置error。3.3 使用read与write实现命令cp四.系统调用与库函数的比较4.1 使用fputc与fgetc实现cp命令这里使用命令strace来跟踪一个程序执行时所使用的系统调用这里可以看到虽然fgetc与fputc函数是一字节进行操作但是所使用的系统调用确实以4096字节为单位进行操作。再看看read与write这两个系统调用(为了与fgetc和fputc一致将BUFSIZE设置为1)这里可以看到read与write这两个系统调用是1字节进行操作的。4.2 预读入缓输出机制1、read与write只有系统调用才能进入到内核空间。从用户空间进入内核空间的时间消耗很大。当在程序中将buf的大小设置为1时read与write频繁的在用户区与内核区切换故很慢。故read、write这两个函数常被称为Unbuffered IO无用户级缓冲区。预读入与缓输出机制从内核到磁盘之间的数据交互是一个物理操作速度很慢频繁操作会导致速度下降图中红色的缓冲区是一个系统级缓存(大小一般是4096字节)当满时一次性的写入磁盘或者一次性从磁盘读出避免了频繁的物理操作。fputc与fgetc函数fputc与fgetc这两个库函数有一个自己的缓冲区(图中蓝色默认4096大小)当使用这两个函数进行读写时先读写到这个默认的缓冲区满了之后一次性刷新写入内核区避免了在用户区与内核去之间频繁的切换节省了时间。