《Linux进程间通信机制》由会员分享,可在线阅读,更多相关《Linux进程间通信机制(5页珍藏版)》请在金锄头文库上搜索。
1、1.信号 Linux 系统预定义(早先 32 种)64 种信号,一个信号和一个信号值(整型)对应,一个信 号即是一种事件,当信号发出时,触发事件处理函数,系统为预定义信号定义了默认事件 处理函数。 SIGALRM 超时告警 SIGINT 终端中断 (Ctrl+C 将产生该信号) SIGKILL *终止进程 SIGUSR1 *用户自定义信号 1 SIGUSR2 *用户自定义信号 2 SIGCHLD 子进程已停止或退出 SIGCONT *让暂停的进程继续执行 SIGSTOP *停止执行(即“暂停“) 注意:SIGKILL 和 SIGSTOP 不能被捕获,即,这两种信号的事件处理函数不能被用户重新定
2、 义。 (1)信号的捕获,即信号和时间处理函数的链接实现 包含头文件#include Signal -help man 2 signaltypedef void (*sighandler_t)(int);/定义函数指针 sighandler_t signal(int signum, sighandler_t handler);/参数 1 是信号值,参数 2 是信号的事件 响应函数(可以取特殊值:SIG_IGN 忽略信号 SIG_DFL 恢复默认行为) ,一般不判定返回值。Sigaction -help man 2 sigaction int sigaction(int signum, cons
3、t struct sigaction *act, struct sigaction *oldact);结构 struct sigaction struct sigaction void (*sa_handler)(int); /* 信号的响应函数 */ sigset_t sa_mask; /* 是一个信号集,该进程将 */ int sa_flags; /* 当 sa_flags 中包含 SA_RESETHAND 时,接受到该信号并调用指定的信号处理函数执行之后,把该信号的响应行为重置为默认行为 SIG_DFL */.信号集的概念:用来表示包含多个信号的集合,用 sigset_t 类型表示,实质
4、是一个无符号 长整形。位运算实现操作。 信号集的基本操作sigemptyset 把信号集清空sigfillset 把所有已定义的信号填充到指定信号集sigdelset 从指定的信号集中删除指定的信号sigaddset 从指定的信号集中添加指定的信号sigismember 判断指定的信号是否在指定的信号集中如果是,返回 1 如果不是,返回 ,信号无效, 返回-1 进程的信号屏蔽字概念:进程的“信号屏蔽字”是一个信号集,当该信号集中的信号产生 时,该进程不会接受到! int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);参数
5、:how:SIG_BLOCK 把参数 set 中的信号添加到信号屏蔽字中SIG_UNBLOCK 把参数 set 中的信号从信号屏蔽字中删除SIG_SETMASK 把参数 set 中的信号设置为信号屏蔽字Oldest 返回原来的信号屏蔽字 获取未处理的信号:当进程的信号屏蔽字中信号发生时,这些信号不会被该进程接受到, 可通过 sigpending 函数(man 2 sigpending)获取这些已经发生了但是没有被处理的信号. (2)信号的发送 Kill -help man 2 kill #include #include int kill(pid_t pid, int sig);alarm h
6、elp man 2 alarm #include unsigned int alarm(unsigned int seconds);信号使用简单,但只能传递信号值本身。 2.管道 管道只能在具有亲戚关系的进程之间实现,管道的读写端对应管道描述符数组:fd0-读, fd1-写。 管道的创建: Pipe help man 2 pipe #include int pipe(int filedes2);3.命名管道 FIFO 命名管道以普通文件的形式(在文件系统中有一个确定的路径和文件名)存在, 无名管道 (即管道) ,是通过文件描述符的形式使用。 管道的创建: #include #include i
7、nt mkfifo(const char *pathname, mode_t mode);成功返回 0,失败返回-1. 命名管道可以向普通文件一样进行读和写,在非阻塞模式下,一个进程的非正常结束,可 能造成另一个进程读或者写的阻塞。 4.共享内存 两个进程之间共享一段物理内存。不同进程可以对这段物理内存进行读和写。 创建共享内存: int shmget (key_t key, size_t size, int shmflg);参数:1)key 共享内存的键值特殊键值:IPC_PRIVATE,该共享内存该创建进程所独享,仅能用于父子进程间 的通信。在消息队列和信号量中同样适用键值这个概念。2)s
8、ize 共享内存的大小,单位为字节3)标志,和 open 的 mode 类似特殊标志:IPC_CREAT 创建共享内存,多次“创建”不是错误 返回值:成功: 返回一个非负整数,作为共享内存的标识符。失败:返回-1 共享内存的链接,返回一个地址指针,进程通过返回的指针,对共享内存读和写:void *shmat(int shmid, const void *shmaddr, int shmflg);参数 1:即为 shmget 的返回值。 参数 2:指定关联到该进程的什么位置,一般取 0,让系统自动选择。 参数 3:如果使用 SHM_RDONLY 则该段共享内存是只读的,即使访问权限允许写操作,一
9、 般取 0 返回:返回一个本进程空间内的虚拟指针,该指针关联到共享内存。 读写结束共享内存后,分离地址指针和进程之间的联系,即释放这个地址,下一个进程使 用的时候,再次通过连接获得一个地址。 int shmdt(const void *shmaddr);参数:即为 shmat 的返回值 注意:仅分离,并不删除该共享内存。 返回值:成功,返回 0,失败,返回-1 共享内存的控制: #include #include int shmctl(int shmid, int cmd, struct shmid_ds *buf)参数: cmd: IPC_STAT 获取当前状态,返回给参数 3 IPC_SE
10、T 设置共享内存(如果权限允许) IPC_RMID(常用) 删除该段共享内存 5. 信号量 信号量不能在进程之间实现数据交换,可以实现临界区的互斥访问。 实现原理:进入临界区之前,执行 P 操作,检测信号量的值,若大于 0,则进入临界区执 行,若等于 0,则进程阻塞挂起,执行完临界部分后,执行 V 操作,先检测队列中是否有 进程处于睡眠状态,若有,则唤醒该进程,若没有,则信号量的值加 1. 信号量的获取: #include #include int shmget(key_t key, size_t size, int shmflg);参数 1 是键值,参数 2 是获取信号量的个数,参数 3 标
11、志:IPC_CREAT,如果该信号量未存 在,则创建该信号量,成功返回大于 0 的信号量的值,失败返回-1. 信号量的操作: #include #include #include int semop(int semid, struct sembuf *sops, unsigned nsops);对信号执行 P 操作或者是 V 操作 struct sembuf short sem_num; 取 0,只获取一个信号量 short sem_op; / -1, 表示 P 操作, 1, 表示 V 操作short sem_flg; / SEM_UNDO : 如果进程在终止时,没有释放信号量,则自动 释放该
12、信号量 信号量的控制:#include #include #include #include #include int msgget(key_t key, int msgflg);参数 2 和获取信号量以及获取共享内存一样,IPC_CREAT。 成功返回消息队列的标志符,失败返回-1. 消息的发送和接收: #include #include #include int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);msqid: 获取的消息队列的标志符 msgp:存放需要发送的消息或是接收消息的地址,需自己定义结构体 s
13、truct msg_struct long int msg_type;/是必须的,指定消息类型,char bufferMSG_SIZE;/自由定义 ;Msgsz:实际消息的大小 sizeof(struct msg_struct)-sizeof(long int) Msgflg:取 0 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);msgtyp:需要接受的消息类型 0: 从消息队列中获取第一个消息,以实现顺序接受(先发先收)0:从消队列中获取相同类型的第一个消息#include #include int msgctl(int msqid, int cmd, struct msqid_ds *buf);删除消息队列:msgctl(msgid,IPC_RMID,0);成功返回 0,失败返回-1.