加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 钦州站长网 (https://www.0777zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

linux基础复习(8)进程通信

发布时间:2022-10-24 15:12:00 所属栏目:Unix 来源:
导读:  数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。

  共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。

  通知事
  数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。
 
  共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。
 
  通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
 
  资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。
 
  进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
 
  UNIX 进程间通信(IPC)方式包括管道、FIFO、信号。
 
  Linux 中使用较多的进程间通信方式主要有以下几种。
 
  (1)管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
 
  (2)信号(Signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知接受进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的。
 
  (3)消息队列:消息队列是消息的链接表,包括Posix 消息队列systemV 消息队列。它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以向消息队列中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息。
 
  (4)共享内存:可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。
 
  (5)信号量:主要作为进程间以及同一进程不同线程之间的同步手段。
 
  (6)套接字(Socket):这是一种更为一般的进程间通信机制,它可用于不同机器之间的进程间通信,应用非常广泛。
 
  [b]管道通信[/b]
 
  普通的Linux shell都允许重定向,而重定向使用的就是管道。例如:
 
  ps | grep vsftpd
 
  管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。
 
  管道主要用于不同进程间通信。
 
  创建一个简单的管道,可以使用系统调用pipe( )。它接受一个参数,也就是一个包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。
 
  系统调用:pipe( );
 
  原型:int pipe( int fd[2] );
 
  返回值:如果系统调用成功,返回0。如果系统调用失败返回- 1:
 
  errno = EMFILE (没有空闲的文件描述符)
 
  EMFILE (系统文件表已满)
 
  EFAULT (fd数组无效)
 
  注意:fd[0] 用于读取管道,fd[1] 用于写入管道。
 
  #i nclude
 
  #i nclude
 
  #i nclude
 
  #i nclude
 
  int main()
 
  {
 
  int pipe_fd[2];
 
  if(pipe(pipe_fd)0)
 
  {
 
  printf("pipe create error\n");
 
  return -1;
 
  }
 
  else
 
  printf("pipe create success\n");
 
  close(pipe_fd[0]);
 
  close(pipe_fd[1]);
 
  }
 
  管道主要用于不同进程间通信。实际上,通常先创建一个管道,再通过fork函数创建一个子进程。
 
  可以通过打开两个管道来创建一个双向的管道。但需要在子进程中正确地设置文件描述符。
 
  必须在系统调用fork( )中调用pipe( ),否则子进程将不会继承文件描述符。
 
  当使用半双工管道时,任何关联的进程都必须共享一个相关的祖先进程。因为管道存在于系统内核之中,所以任何不在创建管道的进程的祖先进程之中的进程都将无法寻址它。而在命名管道中却不是这样。
 
  与linux中文件操作有文件流的标准I/O一样,管道的操作也支持基于文件流的模式。接口函数如下
 
  库函数:popen();
 
  原型: FILE *popen ( char *command, char *type);
 
  返回值:如果成功,返回一个新的文件流。如果无法创建进程或者管道,返回NULL。
 
  管道中数据流的方向是由第二个参数type控制的。此参数可以是r或者w,分别代表读或写。但不能同时为读和写。在Linux系统下,管道将会以参数type中第一个字符代表的方式打开。所以unix进程通信,如果你在参数type中写入rw,管道将会以读的方式打开。
 
  使用popen()创建的管道必须使用pclose( )关闭。其实,popen/pclose和标准文件输入/输出流中的fopen() / fclose()十分相似。
 
  库函数: pclose();
 
  原型: int pclose( FILE *stream );
 
  返回值: 返回系统调用wait4( )的状态。
 
  如果stream无效,或者系统调用wait4( )失败,则返回 -1。
 
  注意此库函数等待管道进程运行结束,然后关闭文件流。
 
  库函数pclose( )在使用popen( )创建的进程上执行wait4( )函数。当它返回时,它将破坏管道和文件系统。
 
  #i nclude
 
  #i nclude
 
  #i nclude
 
  #i nclude
 
  #define BUFSIZE 1024
 
  int main()
 
  {
 
  FILE *fp;
 
  char *cmd = "ps -ef";
 
  char buf[BUFSIZE];
 
  buf[BUFSIZE] = '\0';
 
  if((fp=popen(cmd,"r"))==NULL)
 
  perror("popen");
 
  while((fgets(buf,BUFSIZE,fp))!=NULL)
 
  printf("%s",buf);

(编辑:PHP编程网 - 钦州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章