进程通信 :每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进 程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间 拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信 (IPC,InterProcess Com)。
一.结构图
这张图片也是从别人的博客中down下来的,本人认为对学习这部分知识很有帮助。
二.同一主机间进程通信
1.UNIX进程通信方式
a.无名管道(匿名管道)
1).#include<unistd.h>
pid_t fork(void);
2).#include<unistd.h>
int pipe(int pipefd[2]);
3)四种情况
1>.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像 读到文件末尾一样。
2>.如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管道写 端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
3>.如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
4>.如果有指向管道读端的文件描述符没关闭(管道读端的引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。
b.命名管道
1). int mkfifo(const char *path,mode_t mode);
2).int mknod(const char *path,mode_t mod,dev_t dev);
c.信号
1).#include<signal.h>
int sigemptyset(sigset_t* set); //清理信号集,使其中的所有信号的对应bit清零
int sigfillset(sigset_t* set); //初始化set所指向的信号集,表示该信号的有效信号包括系统支持的所有所有信号。
上面的函数使得信号集处于确定状态
int sigaddset(sigset_t* set,int signo); //在信号集中添加某种有效信号。
int sigdelset(sigset_t* set,int signo); //在信号集中删除某种有效信号。
上面函数在信号集中添加或删除某种有效信号
int sigismember(const sigset_t* set,int signo); //判断一个信号集中有效信号是否包含某种信号。
int sigprocmask(int how,const sigset_t* set,sigset_t* oset);
if(oset != NULL),当前信号屏蔽字通过oset参数传出。
if(set != NULL),则更改进程的屏蔽字,参数how指示如何更改。
if(oset != NULL && set != NULL),则将原来的屏蔽字备份到oset中,然后根据set和how参数更改信号屏蔽字。
how参数的定义:SIG_BLOCK:希望屏蔽的信号,相当于 mask = mask | set;
SIG_UNBLOCK:希望解除阻塞的信号,相当于 mask = mask& - set;
SIG_SETMASK:设置当前信号屏蔽字为set所指的值,相当于 mask = set;
int sigpending(sigset_t* set); // 读取当前进程的未决信号集,通过set参数传出。
int sigaction(int signo,const struct sigaction* act,struct sigaction* oact); //捕捉信号
if(act != NULL),则根据act修改该信号的处理动作。
if(oact != NULL),则根据oact修改该信号的处理动作。
int pause(void); //使得调用进程挂起直到信号递达。
终止进程:pause()函数没有机会返回。
忽略:则进程继续处于挂起状态,pause不返回。
捕捉:则在调用信号处理函数之后pause返回-1,errno设置为EINTR。
2).竞态条件:由于时序问题而导致错误,称为竞态条件
int sigsuspend(const sigset_t* sigmask); //sigsupend()包含了pause的挂起等待功能,同时解决了竞态条件问题。
2.System V通信方式
a.信号量
1).key_t ftok(const char *pathname, int proj_id);
2).int semget(key_t key, int nsems, int semflg);
3).int semget(key_t key, int nsems, int semflg);
4).int semctl(int semid, int semnum, int cmd, ...);
b.消息队列
1).int msgget(ket_t key,int msgflg);
2).ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
3).int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
c.共享内存
三.不同主机间通信
a.RPC
b.Socket
以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。