IO进程学习——7

一、进程间通信(补)

2.信号

软件层次模拟中断

1.信号的处理方式:

(1)忽略信号,信号产生不去关注

(2)默认处理方式(按系统默认方式处理)

(3)捕获信号,捕获之后可以做相应的处理

(4)特殊信号:-9 SIGKILL(结束进程) 和 -19 SIGSTOP(暂停进程) 这两个信号无法被忽略、捕获、阻塞,必须采取默认处理。

2.kill函数

函数的功能:给指定进程发送指定的信号

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <signal.h>

函数原型:

​ int kill(pid_t pid, int sig);

函数参数说明:

​ 1.pid:进程ID

​ 2.sig:信号

​ 常见的信号:

​ SIGINT:中断信号,ctrl+c

​ SIGKILL:结束进程,必须执行默认操作即结束进程

​ SIGALRM:闹钟信号,默认会导致进程结束

​ SIGCONT:将停止态的进程恢复到运行态

​ SIGSTOP:暂停进程,使进程进入停止态,必须执行默认操作

​ SIGTSTP:暂停进程,ctrl+z

​ SIGCHLD:子进程状态改变,默认处理是忽略

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

3.raise函数

函数的功能:给调用者自己发送指定信号

函数使用需要的头文件:

​ #include <signal.h>

函数原型:

​ int raise(int sig);

函数参数说明:

​ 1.sig:信号

函数返回值说明:

​ 成功:返回0

​ 失败:返回非零的数据

4.signal函数

函数的功能:按照程序所想处理信号,捕获信号

函数使用需要的头文件:

​ #include <signal.h>

函数原型:

​ typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

函数参数说明:

​ 1.signum:需要捕获的信号

​ 2.handler:信号处理方式

​ 1.SIG_IGN:忽略信号

​ 2.SIG_DFL:按照默认方式处理

​ 3.信号处理函数,该函数void handler(int arg);

函数返回值说明:

​ 成功:返回信号处理函数的入口地址

​ 失败:返回SIG_ERR,并且设置全局错误号

5.alarm

alarm:定时,时间到到触发SIGALRM信号

pause:等待信号响应

3.共享内存

借助一片的内存空间进行数据交互

优势:效率极高

程序编写流程:

  1. 创建/打开共享内存
  2. 映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
  3. 使用共享内存进行数据交互
  4. 撤销共享内存映射
  5. 删除共享内存对象

1.shmget

函数的功能:创建或打开共享内存对象

函数使用需要的头文件:

​ #include <sys/ipc.h>

​ #include <sys/shm.h>

函数原型:

​ int shmget(key_t key, size_t size, int shmflg);

函数参数说明:

​ 1.key:标识ipc对象的键值

​ IPC_PRIVATE:作用于亲缘间进程通信

​ ftok函数得到的key值可以用于非亲缘间进程通信

​ 2.size:共享内存大小

​ 3.shmflg:共享内存的操作权限

​ IPC_CREAT:共享内存不存在则创建

函数返回值说明:

​ 成功:返回共享内存对象的id

​ 失败:返回-1,并且设置全局错误号

2.shmat

函数的功能:映射共享内存空间

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/shm.h>

函数原型:

​ void *shmat(int shmid, const void *shmaddr, int shmflg);

函数参数说明:

​ 1.shmid:共享内存对象id

​ 2.shmaddr:共享内存的位置,传入NULL使用系统选择的空间

​ 3.shmflg:程序操作共享内存的权限,0为可读可写

函数返回值说明:

​ 成功:返回映射的共享内存地址

​ 失败:返回-1,并且设置全局错误号

3.shmdt

函数的功能:取消内存映射

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/shm.h>

函数原型:

​ int shmdt(const void *shmaddr);

函数参数说明:

​ 1.shmaddr:共享内存映射后的地址

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

4.shmctl

函数的功能:控制共享内存

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/shm.h>

函数原型:

​ int shmctl(int shmid, int cmd, struct shmid_ds *buf);

函数参数说明:

​ 1.shmid:共享内存对象id

​ 2.cmd:

​ IPC_STAT:获取共享内存状态

​ IPC_SET:设置共享内存属性

​ IPC_RMID:销毁共享内存对象

​ 3.buf:

​ 用于存储获取的或者配置的共享内存属性的结构体变量地址

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

4.消息队列

消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息。可以按照消息类型来进行消息读写

1.msgget

函数的功能:创建或打开消息队列对象

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/msg.h>

函数原型:

​ int msgget(key_t key, int msgflg);

函数参数说明:

​ 1.key:标识ipc对象的键值

​ IPC_PRIVATE:作用于亲缘间进程通信

​ ftok函数得到的key值可以用于非亲缘间进程通信

​ 2.msgflg:消息队列对象的操作权限

​ IPC_CREAT:消息队列对象不存在则创建

函数返回值说明:

​ 成功:返回消息队列对象的id

​ 失败:返回-1,并且设置全局错误号

2.msgsnd

函数的功能:发送消息到消息队列对象

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/msg.h>

函数原型:

​ int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

函数参数说明:

​ 1.msqid:消息队列id

​ 2.msgp:发送的消息结构体变量地址

​ 3.msgsz:消息长度

​ 4.msgflg:

​ IPC_NOWAIT:消息没有发送完成函数也会立即返回。

​ 0:直到发送完成函数才返回

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

3.msgrcv

函数的功能:接收消息从消息队列对象

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/msg.h>

函数原型:

​ ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

函数参数说明:

​ 1.msqid:消息队列id

​ 2.msgp:接收的消息结构体变量地址

​ 3.msgsz:消息长度

​ 4.msgtyp:

​ 0:接收消息队列中第一个消息。

​ 大于0:接收消息队列中第一个类型为msgtyp的消息.

​ 小于0:接收消息队列中类型值不小于msgtyp的绝对值且类型值又最小的消息。

​ 5.msgflg:

​ 0:若无消息函数会一直阻塞

​ IPC_NOWAIT:若没有消息,进程会立即返回ENOMSG。

函数返回值说明:

​ 成功:返回接收到的消息的长度

​ 失败:返回-1,并且设置全局错误号

4.msgctl

函数的功能:控制消息队列对象

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/msg.h>

函数原型:

​ int msgctl(int msqid, int cmd, struct msqid_ds *buf);

函数参数说明:

​ 1.msqid:消息队列id

​ 2.cmd:

​ IPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区

​ IPC_SET:设置消息队列的属性。这个值取自buf参数。

​ IPC_RMID:从系统中删除消息队列对象。

​ 3.buf:

​ 存储控制或获取的消息队列属性的结构体变量地址

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

5.信号灯集(配合共享内存使用)

System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯

通常可以配合共享内存一起使用,通过信号灯集的使用实现同步互斥效果,以保证临界资源的安全

1.semget

函数的功能:创建或打开信号灯集对象

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/sem.h>

函数原型:

​ int semget(key_t key, int nsems, int semflg);

函数参数说明:

​ 1.key:标识ipc对象的键值

​ IPC_PRIVATE:作用于亲缘间进程通信

​ ftok函数得到的key值可以用于非亲缘间进程通信

​ 2.nsems:信号灯的个数

​ 3.semflg:

​ 信号灯集的操作权限

​ 示例IPC_CREAT|0666

函数返回值说明:

​ 成功:返回信号灯集对象的id

​ 失败:返回-1,并且设置全局错误号

2.semop

函数的功能:控制信号灯完成PV操作的主要函数

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/sem.h>

函数原型:

​ int semop(int semid, struct sembuf *sops, size_t nsops);

函数参数说明:

​ 1.semid:信号灯集的id

​ 2.sops:存储信号灯集操作的结构体变量地址

​ struct sembuf {

​ short sem_num; //要操作的信号灯的编号

​ short sem_op; //0 :等待,直到信号灯的值变成0

​ //1 :释放资源,V操作

​ //-1:分配资源,P操作

​ short sem_flg; // 0, IPC_NOWAIT, SEM_UNDO

​ };

​ 3.nsops:要操作的信号灯的个数

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

3.semctl

函数的功能:配置信号灯属性

函数使用需要的头文件:

​ #include <sys/types.h>

​ #include <sys/ipc.h>

​ #include <sys/sem.h>

函数原型:

​ int semctl(int semid, int semnum, int cmd, ...

函数参数说明:

​ 1.semid:信号灯集的id

​ 2.semnum:需要控制的信号灯编号

​ 3.cmd:控制效果

​ GETVAL:获取信号灯的值

​ SETVAL:设置信号灯的值

​ IPC_RMID:从系统中删除信号灯集合

​ 4.:如果第三个参数选择设置信号灯的值则该参数可以传递具体设置的值

函数返回值说明:

​ 成功:返回0

​ 失败:返回-1,并且设置全局错误号

总结

pipe: 具有亲缘关系的进程间,单个管道接口是单工,数据在内存中

fifo: 可用于任意进程间,双工,有文件名,数据在内存

signal: 唯一的异步通信方式

msg:常用于cs模式中, 按消息类型访问 ,可有优先级

shm:效率最高(直接访问内存) ,需要同步、互斥机制

sem:配合共享内存使用,用以实现同步和互斥