1、一、linux系统调用及API 1. 系统调用 linux分为内核空间和用户空间,用户空间无法直接访问内核空间。内核通过系统调用为用户提供服务,很精简,大约250个左右。大致可分为:进程控制、进程间通信、文件系统控制、系统控制、存储管理、网络管理、socket控制、用户管理等几类。 2. C库API C库提供若干API,遵循一定的标准,供用户使用。 用户可以直接调用系统调用,也可以调用C库提供的API。
2、二、linux中文件及文件描述符概述 linux主要有4中文件:普通文件、目录文件、链接文件、设备文件。 linux使用文件描述符操作文件,莱姥瞟痖尤其对于用户态来说更是如此,文件描述符是一个非负的整数,是个索引值,linux打开文件时动态分配,分配时,优先分配未使用的最小描述符。打开文件时,内核返回给进程1个文件描述符,读写时进程用此描述符操作文件。 进程打开时,默认会打开三个文件描述符,三个文件默认均指向终端: STDIN_FILENO: 0,标准输入 STDOUT_FILENO: 1,标准输出 STDERR_FILENO: 2,标准错误
3、三、底层文件IO操作 3.1 基本文件操作 3.1.1 函数说明 5个基本函数,不带缓冲,不属于ANSI C,属于POSIX标准。 open、read、write、lseek、close, 见APUE相关笔记。
4、2 文件锁 3.2.1 共享问题如上图,进程信息中包含“打开文件的当前文件偏移量”,由进程各自维护。若进程1打开了文件并定位到文件尾部——>切换到进程2,进程2定位到文件尾部并写了100个字节——>在回到进程1,写了10个字节——>则结果是该文件的最后100个字节中,前10个是进程1写的,并覆盖了原来进程2写的前10个字节,而后90个是进程2写的。 事与愿违,故有的场合期望对文件操作时独占的,所以引入的记录锁。 只要多个进程操作同一个文件,就应该上锁。 3.2.2fcntl()
5、【注意】: !记录锁继承性等问题进程、文件关闭与锁的关系由于锁是在进程信息里存放的,故关闭进程或者关闭文件,该文件的锁有自动关闭。由fork产生的子进程不继承父进程的锁。执行exec后,新进程可以继承原来的锁。默认继承 死锁举例 如图,进程1锁文件1,进程2锁文件2。若进程1想锁文件2,且选择了阻塞方式,则进程1会处于阻塞状态,同理进程2也是。这样就构成了死锁。 使用方法: 使用F_GETLK后再F_SETLK,不是原子操作,可能会出问题。可以直接用F_SETLK,然后判断返回值。
6、3 多路复用3.3.1 IO模型阻塞IO,若IO没有完成相关功能,则进程挂起,直到相关数据到达后才返回。 管道、终垮逆解仔端、网络设备的读写经常出现这种情况。非阻塞IO,IO操作不能完成,理解返回,该进程不睡眠多路转换,轮训各IO,超时等待,select和poll就属于此类信号驱动IO,signal3.3.2 函数说明select函数期望对文件描述符分类处理,处理的对象是 描述符的集合,需要使用相关宏定义FD_ZERO(fd_set *set) 清除一个文件描述符集FD_SET(int fd, fd_set *set) 将一个文件描述符加入文件描述符集中FD_CLR(int fd, fd_set *set) 将一个文件描述符从文件描述符集中清除FD_ISSET(int fd, fd_set*set)如果文件描述符 fd 为 fd_set 集中的一个元素,则返回非零值,可以用于调用 select()之后测试文件描述符集中的文件描述符是否有变化#include <sys/types.h>