LTZ看书之APUE11

LTZ看书之APUE11

13章在讲Daemon Process,没什么特别好写的。
14 ->高级IO

低速系统调用,也就是有信号发生会返回 errno 为 EINTR的

磁盘文件IO虽然有延时,但是这个不能算是低速系统调用

APUE介绍的低速系统调用
PIPE,终端设备,网络设备 读写
读无数据/写无空间(例如TCP卡Congestion window)

打开某些特殊文件
加记录锁的文件读写
ioctl,IPC


文件锁又叫做 byte-range locking,针对特定的文件区域,适合数据库文件
Posix标准
int fcntl(int fd, int cmd, .../* struct flock* flockptr */)
cmd -> F_GETLK,F_SETLK,F_SETLKW
F_SETLKW是F_SETLK的Blocking版本 W means wait

重要数据结构是struct flock ->
struct flock {
 short l_type;
 short l_whence;
 off_t l_start;
 off_t l_len;
 pid_t l_pid;
 __ARCH_FLOCK_PAD
};

锁定整个file的方式: l_whence = SEEK_SET, l_start = 0, l_len = 0

l_type的两类lock
F_RDLCK,F_WRLCK这两种锁的特性很像rw lock

不过与读写锁不一样的是或者这样讲
Posix.1没有规定下面这种情况: process A在某文件区间上设置了一把读锁;process B尝试在这个文件区间加上写锁的时候suspend;process C再尝试获取读锁,如果允许

process C拿到读锁,那么process B将会可能永远拿不到写锁,活活饿死

pthread里面的rw lock的实现会在这种情况下suspend掉process C的读锁请求;但是目前文件区域锁的实现我不太确定

这里看文件区域锁还是比较容易带来deadlock的
例如process A锁住F1的某个区域,然后去锁F2的一个区域,这时候F2的这个区域被process B锁住,那么process A就会suspend,如果这个时候process B过来要锁F1的这个区域
就会发生deadlock


关于文件区域锁的继承和释放
1.fork后,文件区域锁并不继承,继承了就完了,不同的process就有可能同时干同一件事情,把数据搞坏
2.close(fd)后 fd对应的文件锁就被释放了,文件锁挂在inode上,close的时候kernel会去扫描对应的inode上与这个PID相关的lock,释放掉,而并不去关心是哪个文件描述符或

者是哪个文件表,这很重要,因为lockf中并不记录fd,他们只是弱关联关系,这个很重要。
3.exec后,文件锁会继承原来执行程序的锁(fork之后拿到的lock),如果fd带有close-on-exec那么根据第二条,这个fd对应的file上的锁都会被释放。


后面讲了STREAMS,感觉linux上用到的不多,需要在编译kernel时动态加载

IO多路转接,主要是为了实现polling既所谓的轮询
主要函数有select,pselect,poll,epoll
select也会算是低速系统调用,那么就有可能被信号打断
pselect有参数可以设定信号屏蔽集,也提供更高精度的timer

poll的方式与select有不太一样的地方,但是功能相同,epoll更适合大数据量。

readv和writev
记住下面两条就够了
一个称为scatter read(散步读);另外一个称为gather write(聚集写)
这两个函数会面对一个buffer链表。


readn和writen
这个比较像现在Android里面socket的read和write方式,保证能read/write n byte数据,在内部做循环
我比较好奇这两个是否会处理signal,想来应该是会处理的,遇到EINTR帮忙重启就好了

我没有找到Bionic库的实现


存储映射IO
这个很重要,mmap用的很多,映射到process空间的位置在 stack以下,heap以上的部分,map完后返回低地址。

#include<sys/mman.h>
void* mmap(void* addr, size_t len, int prot, int flag, int filedes, off_t off)

prot -> PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE
prot指定的对映射存储区的保护不能超过文件的open权限

在 flag为 MAP_FIXED的时候OS会保证分配的memory起始地址为addr,否则只是给OS一个建议。
一般建议addr给0,让OS来决定。

MAP_SHARED是说对映射区域的存储(write)会导致修改该文件。
MAP_PRIVATE则是对映射区域的操作会常见一个映射文件的副本。


后面有个例子用了lseek
使用lseek增加文件长度的方式,先lseek一个值,如果这个值大于文件本身的长度,那么下一次写就会加长该文件,并且在文件
中形成一个空洞,未写过的内容全部读为0。
mmap只能map文件的最大长度,超过的地方没办法同步到文件。

你可能感兴趣的:(LTZ看书之APUE11)