linux进程通信--管道

管道分为有名管道和无名管道。

无名管道:

无名管道是半双工的,就是对于一个管道来讲只能读或者写。就像高速公路一样一条路只能单向行驶。

无名管道,只能在相关的,有亲缘关系的进程使用。例如:一个fork或者exec调用创建的子进程继承了父进程的文件描述符。这时候它就可以和父进程来一起使用无名管道。

创建无名管道的函数:

所需要头文件:#include<unistd.h>

函数原型:int pipe(int fd[2])

函数的传入值:fd[2]:是管道的描述符数组他,在主调函数为数组分配内存,传入数组首地址,间接修改数组的值共主调函数使用。fd[0]代表读,fd[1]代表写。

函数的返回值:失败返回-1,成功返回0

一个简单的无名管道的例子:

/*
 * main.c
 *
 *  Created on: 2015-1-29
 *      Author: hsc
 */

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>

int main(void)
{
    int pipefd[2];
    char buf[1024];
	pid_t pid;

	if(pipe(pipefd) == -1)//创建无名管道
	{
		printf("%s \n", strerror(errno)); //创建管道失败
		return -1;
	}
	pid = fork();//创建进程
	if(pid == -1)
	{
		printf("%s \n", strerror(errno));//出错的情况
		return -1;
	}
	if(pid == 0)
	{
		int len;
		memset(buf,0,sizeof(buf));
		close(pipefd[1]);//close write pipe
		while((len=read(pipefd[0],buf,sizeof(buf)))>0)
		{
			write(STDOUT_FILENO,buf,strlen(buf));
		}
		close(pipefd[0]);
	}
	else
	{
		memset(buf,0,sizeof(buf));
		close(pipefd[0]);//close read pipe
		strcpy(buf,"hello world !\n");

		if(-1 == write(pipefd[1],buf,strlen(buf)))
		{
			printf("%s \n", strerror(errno));
		}
		close(pipefd[1]);
		waitpid(pid,NULL,0);//等待子进程退出
	}
	return 0;
}

有名管道(FIFO):

有名管道是持久稳定的,存在于文件系统。

FIFO除了具有无名管道的所有特性外,它还允许无亲缘关系的进程间通信进行数据交换。

可以通过shell 命令建立有名管道

mkfifo  [option] name

mkfifo 创建一个名为name的有名管道

例如:

mkfifo   fifo

使用cat  <fifo 这里<符号是重定向输入表示从管道fifo读取内容。

重新打开一个终端,到同一目录下执行ls -l>fifo。这里>符号是重定向输出表示向道fifo写内容。

在创建管道成功之后,就可以使用open(),read(),write()这些系统调用,就像操作普通文件一样,对于为读而打开的管道,在open()设置为O_RDONLY,同样为写而打开的管道在open()设置为O_WRONLY,与读写普通文件不同是阻塞问题。当然可以在open()函数设置非阻塞标志O_NONBLOCK。这里对于一个管道可以理解为从管道的一头写另一头读。

对于读进程:

1.如果管道是阻塞打开,且当管道内没有数据,则对于读进程来说将一直阻塞到有数据写入。

2.如果管道是非阻塞打开,则不论管道内是否有数据,读进程都会立即执行读的操作。没有数据,则返回0。

对于写进程:

1.如果管道是阻塞打开,且当管道内没有数据,则对于写进程来说将一直阻塞到有数据可以被写入(比如管道满了)。

2.如果管道是非阻塞打开而不能写入全部数据,则读操作进行的部分写入或者调用失败。

值得注意的是:在数据能被传送之前,管道必须被打开在两端(读和写),正常情况下只open一个它会阻塞直到另外一个open。也就是说你先执行写的管道(FIFO)则程序会

阻塞在open()函数这里,直到运行读管道程序open()。
读程序如下:read_fifo.c 

/*
 * read_fifo.c
 *
 *  Created on: 2015-2-2
 *      Author: hsc
 */
/*
 * main.c
 *
 *  Created on: 2015-2-2
 *      Author: hsc
 */
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include <sys/stat.h>
#include<unistd.h>
#include <fcntl.h>
#include<errno.h>

#define MYFIFO  "myfifo"
#define BUFFSIZE 1024

int main()
{
	int fd; //定义文件描述符
	char buf[BUFFSIZE]; //定义buf
	
	if(access(MYFIFO,F_OK) == -1) //判断管道文件是否存在
	{
		if(mkfifo(MYFIFO,0666)== -1) //6表示有读写权限 0666(0表示是八进制 6表示读写) 对于用户、组、其他都对该文件有读写权
		{
			printf("%s",strerror(errno)); //输出错误原因
			return -1;
		}
	}

	fd = open(MYFIFO,O_RDONLY);// 已只读方式打开管道文件

	if(fd == -1)
	{
		printf("%s",strerror(errno));
		return -1;
	}

	memset(buf,0,BUFFSIZE);//buf 清空

	if(read(fd,buf,BUFFSIZE) ==-1)// 读管道
	{
		printf("%s",strerror(errno));
	}
	else
	{
		printf("read:%s ",buf);
	}

	close(fd);//关闭打开管道
	return 0;

}
写管道程序:write_fifo.c

/*
 * main.c
 *
 *  Created on: 2015-2-2
 *      Author: hsc
 */
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include <sys/stat.h>
#include<unistd.h>
#include <fcntl.h>
#include<errno.h>

#define MYFIFO  "myfifo"
#define BUFFSIZE 1024

int main()
{
	int fd;
	char buf[BUFFSIZE];
	if(access(MYFIFO,F_OK) == -1)
	{
		if(mkfifo(MYFIFO,0666)== -1)
		{
			printf("%s",strerror(errno));
			return -1;
		}
	}

	fd = open(MYFIFO,O_WRONLY);// 已只写方式打开管道文件

	if(fd == -1)
	{
		printf("%s",strerror(errno));
		return -1;
	}

	memset(buf,0,BUFFSIZE);
	strcpy(buf,"hello fifo \n");

	if(write(fd,buf,strlen(buf))>0)//写管道
	{
		printf("write %s success",MYFIFO);
	}
	else
	{
		printf("%s",strerror(errno));
	}

	close(fd);
	return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值