进程通信(IPC)的原因:数据传输,资源共享,通知事件,进程控制
POSIX可移植操作系统接口,IEEE电气和电子工程师协会
linux进程通信方式:管道(pipe)和有名管道(FIFO)
信号(signal)
消息队列
共享内存
信号量
套接字(socket)
1、管道:单向的,先进先出的,把一个进程的输出和一个进程的输入连接在一起。一个进程的管道尾部写入数据,另一个进程的管道头部读出数据
无名管道:用于父进程和子进程之间的通信
int pipe(int filedis[2]);产生两个描述文件filedis[0]用于读管道 ,filedis[1]用于写管道
关闭管道close(filedis[0]);close(filedis[1])
管道通信时先建立管道,然后利用fork建立子进程,子进程会继承父进程所建立的管道
2、信号量
信号量:又名信号灯,主要用途是保护临界资源
二值信号量,只能取0或1。计数信号量,可以取任意非负值
信号量创建和打开:#include
int semgey(key_t key, int nsems, int smflg)
key 由ftok获取 nsems 打开或创建的信号灯集中包含的信号灯数目
semflg标识
信号量操作:int semop (int semid,struct sembuf *sops,unsigned nsops)
semid 信号量集的ID
sops数组,表示要进行的操作
struct sembuf{
unsigned short sem_nem 所取的信号量在集合中的位置,即数组的下标
short sem_op 要进行的操作,1释放,-1获取
short sem_flg IPC_NOWAIT / IPC_IPDO
不阻塞 程序结束时释放
}
nsops, 表示 sops所指向数组的元素个数
3、消息队列
消息队列,就是一个消息链表,具有特定的格式,进程可以按照一定的规则添加消息,另一个进程则可以读取消息
目前主要有两种消息队列,POSIX消息队列和系统V消息队列
系统V消息队列随拟合持续,只有重启内核或者人工删除时,消息队列才会删除
每个消息队列都在系统范围内有一个键值,所以要获得消息的描述字必须先获取键值
键值获取:#include #include
key_t ftok(char *pathname , char proj) proj项目名,不为0 即可
消息创建或者打开: #include #include #include
int msgget(key_t key,int msgflg ) 返回消息队列的描述字 key由ftok获取
msgflg标识位 IPC_CREAT 创建新的消息队列
IPC_EXCL 与IPC_CREAT一起使用,如果要创建的消息存在,返回错误
IPC_NOWAIT 消息队列要求无法得到满足时,不阻塞
如果没有与key值对应的消息队列,并且msgflg中包含 IPC_CREAT则创建新的消息队列
如果key的参数为IPC_PRIVATE 则创建新的消息队列
向消息队列发送消息:int msgsnd(int msqid,struct msgbuf *msgp,int msgsz,int msgflg)
struct msgbuf{
long mtype; 消息类型
char mtext[1]; 消息数据收地址
}
接收消息:int msgrcv(int msqid,struct msgbuf *msgp,int msgsz,long msgtyp,int msgflg)
从msqid代表的队列中读取一个msgtyp类型的消息,保存在msgp中,消息读取后将被删除
4、共享内存
共享内存:被多个进程共享的一部分物理内存,它访问数据快
共享内存的实现:创建共享内存 int shmget(key_t key,int size,int shmflg)创建错误返回-1,成功则返回标识符
key的取值0/PRIVATE, key取PRIVATE时创建一块新的共享内存
key取0 时,而shmflg又设置参数PRIVATE,同样创建一块新的共享内存
size内存的大小
映射:int shmat(int shmid,char *shmaddr,int flag)成功则映射到进程中的地址,失败返回-1
shmid时shmget返回的标识符
flag决定映射的方式,通常为0
解除映射 int shmdt(char *shmaddr)
5、信号
常见的信号:SIGHUP 从终端上发出的结束信号
SIGINT 来自键盘的中断信号ctrl+c
SIGKILL 该信号结束接收信号的进程
SIGTERM kill命令发出的信号
SIGCHLD 标识子进程结束或停止的信号
SIGSTOP 来自键盘(ctrl+z)或调试程序的停止执行信号
信号处理方式:大多数信号忽略,SIGKILL SIGSTOP这两个信号不能忽略
执行用户希望的动作,调用用户函数
执行系统默认动作,大多数情况默认结束进程
发送信号函数#include #include
int kill(pid_t pid,int signo) 可以向自身或者其他进程发送信号
int raise(int signo) 只能向自身发送信号
alarm函数 #include
unsigned int alarm(unsigned int seconds) 经过seconds秒产生一个发送给自己的信号SIGALRM
每个进程只能有一个闹钟时间
pause函数 #include
int pause() 进程等待,直到收到一个信号
信号处理函数signal #include
void(*signal(int signo , void(*func)(int)))(int)
func的值:SIG_IGN 忽略信号
SIG_DFL 默认方式处理
信号处理函数名