Linux下面进程间的通信方式主要有:管道,有名管道,消息队列,信号量,和共享内存,此外还有我上一章讲的信号。
由于进程的地址空间是独立的,所以进程间如果要交互数据必须采用专门的通信机制。
首先我们看一下方式之一:管道。
管道是一种半双工通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用,无亲缘关系的进程不能使用。
管道就是一个特殊的文件,这个文件只存在于内存中,在创建管道时,系统为管道分配一个页面作为数据缓冲区,进行管道通信的两个进程通过读写这个缓冲区来进行通信。
管道的创建原函数:int pipe(int fd[2]);
管道两端分别用描述符fd[0]和fd[1]来表示,fd[0]表示管道的读端,而fd[1]表示管道的写端,该函数创建成功返回0,失败返回-1.下面具体看一个例子,看看怎么使用管道的创建函数。
- #inlcude<stdio.h>
- #include<stdlib.h>
- #inlcude<string.h>
- #include<sys/types.h>
- #include<unistd.h>
- void read_from_pipe(int fd)
- {
- char message[100];
- read(fd,message,100);
- printf("read from pipe %s:\n",message);
- }
- void write_to_pipe(int fd)
- {
- char *message="hello huang!";
-
- write(fd,message,strlen(message) 1);
- }
- int main(void)
- {
- pid_t pid;
- int fd[2];
- if(pipe(fd)){
- printf("create pipe failed\n");
- exit(0);
- }
- pid=fork();
- switch(pid){
-
- case 0:
- close(fd[1]);
- read_from_pipe(fd[0]);
- exit(0);
- case -1:
- printf("fork failed\n");
- exit(0);
- default:
- close(fd[0]);
- write_to_pipe(fd[1]);
- exit(0);
-
- }
- return 0;
- }
这样我们就可以实现父子进程之间的通信了,不过需要注意的一点是,管道必须要在创建子进程前创建,这样子进程才回、会从父进程继承创建的管道,否则子进程不能使用创建的管道的描述符。
那么如果父进程创建了子进程而子进程却调用了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()和文件描述符拷贝操作集成在同一个函数里,而且它保证操作的原子性。
下面具体看一个使用这个函数的例子:
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<string.h>
- int main(int arg,char *argv[],char **envision)
- {
- int fd[2];
- pid_t pid;
- int stat_val;
- if
阅读(1221) | 评论(0) | 转发(0) |