linux系统中的进程通信(管道和有名管道)

进程通信:多个进程需要协调工作,需要进行数据的交换。

管道:是unix中进程通信的一种方式,管道的一端连接着输入另一段连接这数据的输出。

管道(无名管道):用于父子进程之间的通信。

有名管道:由于不同进程之间的通信。


匿名管道:

#include <unistd.h>
int pipe(int fdes[2]) /*创建匿名管道*/
fdes:管道的输入、输出端的描述字。

成功时返回 0,失败时返回 -1

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const int BUFFMAX = 100; 

int main()
{
	pid_t pid;
	int n,mypipe[2];
	char buffer[BUFFMAX + 1],*some = "hello world!";

	if(pipe(mypipe))    /*创建管道*/
	{
		fprintf(stderr,"faile!\n");
		exit(1);
	}

	if((pid = fork()) < 0) /*创建子进程*/
	{
		fprintf(stderr,"faile!\n");
		exit(1);
	}

	if(pid == 0) /*如果是子进程*/
	{
		close(mypipe[1]);   /*关闭子进程管道的输出端*/
		n = read(mypipe[0],buffer,BUFFMAX); /*从管道中读取数据*/
		fprintf(stdout,"Pid %d Read %d %s\n",getpid(),n,buffer);
	}
	else
	{
		close(mypipe[0]); /*关闭父进程管道的输入端*/
		n = write(mypipe[1],some,strlen(some)); /*向管道写入数据*/
                fprintf(stdout,"Pid %d Write %d %s\n",getpid(),n,some);
	}
	exit(0);
}

一般通过fork创建子进程是为了调用exec( )系列函数运行新的程序,如果调用exec( )则子进程从父进程继承的文件描述已经被新的程序代替,在调用exec( )函数之前可以先把管道的输入端重定向到标准输入端,从而是新的程序能过通过管道和父进程通信。重定向一般使用dup2( old,new)函数实现,如果描述字new打开则先关闭,再用new代替old,这个函数的操作是原子。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

const int Max = 100;

int main()
{
	int fd[2];
	pid_t pid;
	char buffer[Max];

	if(pipe(fd))  /*创建管道*/
	{
		fprintf(stderr,"make falie!\n");
		exit(1);
	}

	if((pid = fork()) < 0) /*创建子进程*/
	{
		fprintf(stderr,"pid faile!\n");
		exit(1);
	}

	if(pid == 0)  /*如果是子进程*/
	{
		close(fd[1]); /*关闭子进程管道的输出端*/
		dup2(fd[0],0); /*把子进程的输入端重定向到标准输入端*/
		close(fd[0]);  /*关闭不需要的描述字*/

		if(execl("/bin/cat","cat",NULL) < 0)  /*调用execl()创建新的程序*/
		{
			fprintf(stderr,"make falie!\n");
			exit(1);
		}

	}
	else  /*如果是子进程*/
	{
		close(fd[0]); /*关闭父进程管道的标准输入*/
		fprintf(stdout,"Plase input line date!\n");
		dup2(fd[1],1); /*为了使用pets函数,把父进程管道出重定向到标准输出*/
		close(fd[1]);  /*关闭不用的描述字*/
		while(gets(buffer) != NULL) 
			puts(buffer);
	}

	exit(0);
}

有名管道(FIFO)

#include <sys/types.h>

#include <sys/stat.h>
int mkfifo (const char *path,mode_t mode); /*创建有名管道*/
path:有名管道的路径级名字。

mode:有名管道的文件权限。

失败返回0

创建管道,并读取内容,如果还没有向管道写入内容,将阻塞等待。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define FIFO_FILE "fifo_file" /*有名管道的名称*/
#define Max 5

int main()
{
	int fifo,fd;
	int n;
        char buff[Max]; 

	if(access(FIFO_FILE,F_OK) < 0) /*测试文件是否存在*/
	{
		if(mkfifo(FIFO_FILE,0666) < 0) /*创建管道*/
		{
		 fprintf(stderr,"mkdir falie!\n");
		 exit(1);
		}
	}

	if((fd = open(FIFO_FILE,O_RDONLY)) < 0) /*打开文件*/
	{
		fprintf(stderr,"Open falie!\n");
		exit(1);
	}
	
	printf("%d Open %s\n",getpid(),FIFO_FILE);
	
	while((n = read(fd,buff,Max)) > 0) /*读取管道内容*/
	{
		fprintf(stdout,"%d read %s\n",getpid(),buff);
	}
	close(fd); /*关闭文件*/
	fprintf(stdout,"%d over\n",getpid());
	exit(0);
}

打开文件向管道写入数据,当管道内容还没有读取时将阻塞,等待读取完毕在写入。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define FIFO_FILE "fifo_file"
#define Max 100
int main()
{
	int fifo,fd;
	int n;
        char buff[Max + 1] = "hello fifo"; 

	if((fd = open(FIFO_FILE,O_WRONLY)) < 0) /*打开文件*/
	{
		fprintf(stderr,"fifo1 Open falie!\n");
		exit(1);
	}
	
	printf("%d Open %s\n",getpid(),FIFO_FILE);
	
	n = write(fd,buff,strlen(buff)); /*向管道内写入文件*/
	fprintf(stdout,"%d write %d\n",getpid(),n);
	
	close(fd); /*关闭文件*/
	fprintf(stdout,"%d over\n",getpid());
	exit(0);
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值