APUE主要讨论了三部分内容:文件IO、并发、进程间通信
• 文件IO:
标准IO:优点是可移植性高,缺点是性能比系统 IO 差,且功能没有系统 IO 丰富。
系统IO:因为是内核直接提供的系统调用函数,所以性能比标准 IO 高,但是可移植性比标准 IO 差。
• 并发:
信号 + 多进程;
多线程;
进程间通信:
FIFO:管道;
System V:又称为 XSI,支持以下三种方式:
msg:消息队列;
sem:信号量;
shm:共享存储;
Socket:套接字(网络通信);
• 文件描述符
对于内核而言,所有打开的文件都是通过文件描述符引用,文件描述符是一个非负整数。当打开或者创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,使用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
• 文件IO函数
1:lseek(设置文件偏移量)
#include
off_t lseek(int fd,off_t offset,int whence) //返回值: 若成功,返回新的文件偏移量 若出错 返回-1
每个打开文件都有一个与其相关联的“当前文件偏移量”。它通常是一个非负整数,用以度量从文件开始处计算的字节数,通常读写都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。
2:write(向打开的文件写数据)
#include
ssize_t write(int fd,const void* buf,size_t nbytes)//返回值:若成功 返回已经写的字节数 若出错 返回-1
3:read函数(从打开的文件中读数据)
#include
ssize_t read(int fd,void* buf,size_t nbytes)//返回值: 读到的字节数,若已到文件尾 返回0;若出错,返回-1
做个例子熟悉下这几个函数吧
1 #include"apue.h"
2 #include
3 #include
4 #include
5
6 int main()
7 {
8 int fd,byteNum,result;
9 char wbuf[10] = "123456789";
10 if((fd=open("./a.txt",O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
11 perror("Fail to open\n");
12 }else{
13 printf("open\n");
14 }
15 if((byteNum=write(fd,wbuf,10))<0){
16 perror("Fail to write\n");
17 return -1;
18 }else{
19 printf("byteNum - %d\n",byteNum);
20 }
21 }
1 #include"apue.h"
2 #include
3 #include
4 #include
5
6 int main()
7 {
8 int fd,byteNum,result;
9 char wbuf[10] = "123456789";
10 char nbuf[5] = "ABCDE";
11 if((fd=open("./a.txt",O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
12 perror("Fail to open\n");
13 }else{
14 printf("open\n");
15 }
16 if((byteNum=write(fd,wbuf,10))<0){
17 perror("Fail to write\n");
18 return -1;
19 }else{
20 printf("byteNum - %d\n",byteNum);
21 }
22 if((byteNum=write(fd,wbuf,3))<0){
23 perror("Fail to write\n");
24 return -1;
25 }else{
26 printf("byteNum - %d\n",byteNum);
27 }
28 return 0;
29 }
1 #include"apue.h"
2 #include
3 #include
4 #include
5
6 int main()
7 {
8 int fd,byteNum,result;
9 char wbuf[10] = "123456789";
10 char nbuf[5] = "ABCDE";
11 if((fd=open("./a.txt",O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IXUSR))<0){
12 perror("Fail to open\n");
13 }else{
14 printf("open\n");
15 }
16 if((byteNum=write(fd,wbuf,10))<0){
17 perror("Fail to write\n");
18 return -1;
19 }else{
20 printf("byteNum - %d\n",byteNum);
21 }
22
23 //lseek
24 if((result = lseek(fd,4,SEEK_SET))<0){
25 perror("Fail to lseek\n");
26 }else{
27 printf("New offet of this file:%d\n",result);
28 }
29 return 0;
30 }
30 //read
31 if((byteNum = read(fd,rbuf,12))<0){
32 perror("Fail to read\n");
33 }else{
34 printf("byteNum = %d\n",byteNum);
35 }
36 return 0;
读到了文件终结符,因为wbuf只给了9个字符,在write后第十个字符变成了EOF。
• 文件共享
打开文件的内核数据结构(抄别人的图)
两个进程同时打开一个文件(抄别人的图)
我们假定第一个进程在文件描述符3上打开该文件,而另一个进程在文件描述符4上打开该文件,打开该文件的每一个进程都会获得各自的一个文件表项,但对于一个给定的文件只有一个v节点表项。之所以每个进程都获得自己的文件表项,是因为这可以使每个进程都有它自己的对该文件的当前偏移量。
当多个进程同时操作一个文件时,可能会产生预想不到的后果,需要通过原子操作来解决。
• 原子操作
对于原子操作重点在于理解概念啦,pread和pwrite就不demo了,多线程玩的不熟,有时间在补充。
一般而言,原子操作指的是由多步组成的一个操作。如果该操作原子地执行,则要么全部执行,要么全部不执行。(这个概念实在太常见,数据库的事件,操作系统的PV操作。。。)
好了,公司阿姨关灯撵我走,后面的巴拉巴拉函数有空在demo吧,突然怀恋实验室。