Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1496567
  • 博文数量: 148
  • 博客积分: 2234
  • 博客等级: 大尉
  • 技术积分: 3225
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-17 21:34
个人简介

未来很长。

文章存档

2017年(7)

2016年(4)

2015年(1)

2014年(6)

2013年(31)

2012年(99)

分类: LINUX

2012-07-24 14:49:06

Linux下面进程间的通信方式主要有:管道,有名管道,消息队列,信号量,和共享内存,此外还有我上一章讲的信号。
由于进程的地址空间是独立的,所以进程间如果要交互数据必须采用专门的通信机制。
首先我们看一下方式之一:管道。
管道是一种半双工通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用,无亲缘关系的进程不能使用。
管道就是一个特殊的文件,这个文件只存在于内存中,在创建管道时,系统为管道分配一个页面作为数据缓冲区,进行管道通信的两个进程通过读写这个缓冲区来进行通信。
管道的创建原函数:int pipe(int fd[2]);
管道两端分别用描述符fd[0]和fd[1]来表示,fd[0]表示管道的读端,而fd[1]表示管道的写端,该函数创建成功返回0,失败返回-1.下面具体看一个例子,看看怎么使用管道的创建函数。

点击(此处)折叠或打开

  1. #inlcude<stdio.h>
  2. #include<stdlib.h>
  3. #inlcude<string.h>
  4. #include<sys/types.h>
  5. #include<unistd.h>
  6. void read_from_pipe(int fd)
  7. {
  8.     char message[100];
  9.     read(fd,message,100);
  10.     printf("read from pipe %s:\n",message);
  11. }
  12. void write_to_pipe(int fd)
  13. {
  14.     char *message="hello huang!";
  15.     
  16.     write(fd,message,strlen(message) 1);
  17. }
  18. int main(void)
  19. {
  20.     pid_t pid;
  21.     int fd[2];
  22.     if(pipe(fd)){
  23.         printf("create pipe failed\n");
  24.         exit(0);
  25.     }
  26.     pid=fork();
  27.     switch(pid){
  28.     
  29.     case 0:
  30.         close(fd[1]);
  31.         read_from_pipe(fd[0]);
  32.         exit(0);
  33.     case -1:
  34.         printf("fork failed\n");
  35.         exit(0);
  36.     default:
  37.         close(fd[0]);
  38.         write_to_pipe(fd[1]);
  39.         exit(0);
  40.             
  41.     }
  42.     return 0;
  43. }
这样我们就可以实现父子进程之间的通信了,不过需要注意的一点是,管道必须要在创建子进程前创建,这样子进程才回、会从父进程继承创建的管道,否则子进程不能使用创建的管道的描述符。
那么如果父进程创建了子进程而子进程却调用了execve()函数去执行了两外一个函数,那么所创建的管道就不能被这个函数所访问了,怎么办呢?Linux中专门有两个函数就是解决这个问题的。
int dup(int oldfd);
int dup2(int oldfd,int newfd);
这两个函数调用成功返回一个oldfd文件描述符的副本,失败返回-1.
先看一下这两个函数的异同:
pid=fork();
if(pid==0)
{
/*关闭子进程的标准输出*/
   close(1);
/*复制管道输入端到标准输出*/
   dup(fd[1]);
  execve("exam",argv,environ);
}
pid=fork();
if(pid==0)
{
/*关闭子进程的标准输出复制管道输入端到标准输出*/
  dup2(1,fd[1]);   
  execve("exam",argv,environ);
}
从上面的例子可以看出dup2()函数的调用将close()和文件描述符拷贝操作集成在同一个函数里,而且它保证操作的原子性。
下面具体看一个使用这个函数的例子:
 

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<sys/types.h>
  5. #include<sys/stat.h>
  6. #include<string.h>
  7. int main(int arg,char *argv[],char **envision)
  8. {
  9.     int fd[2];
  10.     pid_t pid;
  11.     int stat_val;
  12.     if
阅读(1221) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~