1.信号
信号是进程间通信方式之一,是系统用来通知进程发生了某件事的一种手段,仅是一种通知,没有数据传递。
信号的本质是一个整数,不同的信号代表了不同的含义,可以在linux中使用指令kill -l查看系统中的所有信号。
当进程收到信号时,会中止当前的任务,转而去处理信号,处理完成后,再从中止点继续执行原来的任务,所以,信号也可以软中断。
常用的信号:
2) SIGINT 由按键ctrl+c产生,默认中止进程 9) SIGKILL 由用户主动发出,用于结束指定的进程 11) SIGSEGV 由于程序非法使用内存,系统发出该信号,默认终止当前进程 13) SIGPIPE 管道破裂,指在往管道中写数据时,读端不存在了,进程就会收到该信号,默认终止当前进程 14) SIGALRM 闹钟信号 17) SIGCHLD 子进程结束时,会给它的父进程发该信号。linux为了防止僵死进程的产生,默认是忽略这个信号的,但不是所有版本的linux都是这样的,所以,最有效的方式是捕获该信号,然后调用wait/waitpid函数。
常用的信号相关接口:
#include <signal.h> int kill(pid_t pid, int sig); 功能:给指定的进程发送指定的信号 返回: 成功返回0, 失败返回-1,同时设置errno
#include <signal.h> typedef void (*sighandler_t)(int);//定义一个名为sighandler_t的新类型,它是一个函数指针类型,指向一个接收一个整型参数并且返回空类型的函数 sighandler_t signal(int signum, sighandler_t handler); 功能:用于处理指定的信号 参数: signum 需要处理的信号(可以是信号值,也可以是信号名称) handler 信号处理器(本质是一个函数指针,当指定的信号到达,系统自动调用你指定的这个函数) 说明: 信号处理器可以是忽略信号,用SIG_IGN表示 信号处理器可以使用信号的默认处理方式,用SIG_DFL来表示 信号处理器可以是自定义的函数, 该函数要求返回类型为void, 有一个int类型的参数,这个int就是signal的第一个参数,即要处理的信号
#include <unistd.h> unsigned int alarm(unsigned int seconds); 功能:设置一个指定时间的闹钟,时间超时则发出SIGALRM信号 参数: seconds 时间秒数 该参数可以为0,表示取消之前设置的闹钟 返回: 闹钟正常超时,返回0 被取消则返回闹钟的剩余时间
2.无名管道
无名管道在内核中开辟了一块缓冲区,这块内核空间由所有进程共享。
无名管道类似于文件,可以用文件描述符read/write/close操作,但无名管道没有名字,所以不用open获取文件描述符,而是系统专门提供了一个接口pipe。
#include <unistd.h> int pipe(int pipefd[2]); 功能:在内核中创建一个无名单向管道,用于进程间通信 参数: pipefd 是两个元素的整型数组的首地址,由用户提供,内核创建好管道之后,会自动把管道两端的描述符写入该数组 pipefd[0] 是读端描述符, pipefd[1]是写端描述符。 返回: 成功返回0,失败返回-1,同时设置errno
一些说明:
无名管道是单向的;
如果无名管道为空,读数据时会阻塞,直到有数据写入;
如果无名管道满了,写数据时会阻塞,直到数据被读走;
无名管道只能用于具有亲缘关系的进程之间(即有共同祖先)。
3.有名管道
有名管道需要有一个名字存在于文件系统中,任意进程都可以使用该名字来打开这个管道进行读写操作。
#include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); 参数: pathname 待创建的命名管道的名字,建议带路径 mode 创建文件时的权限,一般用八进制表示 返回: 成功返回0, 失败返回-1,同时设置errno
一些说明:
与无名管道相同,创建成功后用文件接口进行读写操作;
只读打开fifo时会阻塞,直到有进程以写的方式打开该fifo,反之亦然;
但是可读可写的方式打开则不会有这个问题。
无名管道和有名管道的区别
无名管道:
1)只能用于共同祖先的进程,一般用于父子进程和兄弟进程之间;
2)是一种半双工的通信方式,数据只能单向流动;
3)创建一块内核资源用于通信,不会在文件系统中留下对应的文件;
有名管道:
1)可以用于任意的进程;
2)是一种全双工的通信方式;
3)使用mkfifo系统调用创建,会在文件系统中留下一个FIFO文件用于通信;
总的来说,无名管道通常用于临时的、简单的通信需求,而有名管道多用于长期的、稳定的跨进程通信需求。
4.信号量
信号量是用于协调(同步)进程或线程间工作的,标识某种共享资源的数量,当多个进程或线程争夺共享资源时,信号量用来保证它们合理、有序的使用这些资源。
可以把信号量理解为一个整数,这个整数就表示资源的数量: 如信号量的值为0,表示没有资源可用,进程不能访问该资源; 如信号量的值为1,表示有1份资源可用,即同一时刻只允许有一个进程去访问共享资源; 如信号量的值为n, 表示同一时刻允许有n个进程去访问共享资源。
当资源可用的情况下, 进程访问共享资源前,需要把信号量的值减1,表示消耗了一份资源,这种操作称为P操作; 进程访问共享资源完成后,需要把信号量的值加1,表示增加了一份资源,这种操作称为V操作。 简称P-V+。
信号的PV操作 是原子性的,也就是说对信号量值的增加或减少,系统保证在CPU级别上是不可分割的,这与普通整数的加减是有本质的区别的。