进程通信总结篇

来源:互联网 发布:c语言 a算法代码 编辑:程序博客网 时间:2024/05/29 15:21

进程通信 :每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进 程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程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


       以上就是本人在学习过程中的一些经验总结。当然,本人能力有限,难免会有纰漏,希望大家可以指正。








1 0
原创粉丝点击