linux的管道和命名管道

时间:2022-12-05 00:13:51

看了个教程,感觉还是要结合代码看。

管道是linux里面进程间通信的一种方式,其他的还有像信号(signal)、信号量、消息队列、共享内存、套接字(socket)等。


1.管道pipe

int pipe( int fd[2] );

返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。

必须在fork()中调用pipe(),否则子进程不会继承文件描述符。两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。


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

int main()
{
int pipe_fd[2];
pid_t pid;
char buf_r[100];
char* p_wbuf;
int r_num;
memset(buf_r,0,sizeof(buf_r));
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
if((pid=fork())==0)
{
printf("\n");
close(pipe_fd[1]); /*关闭写管道描述符*/
sleep(2);
if((r_num=read(pipe_fd[0],buf_r,100))>0){
printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
}
close(pipe_fd[0];
exit(0);
}
else if(pid>0){
close(pipe_fd[0]);
if(write(pipe_fd[1],"hello",5)!=-1)
printf("parent write1 success!\n");
if(write(pipe_fd[1],"pipe",5)!=-1)
printf("parent write2 success!\n");
close(pipe_df[1]);
sleep(3);
waitpid(pid,NULL,0);
exit(0);
}
}

2.流管道

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#define BUFSIZE 1000int 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);	pclose(fp);	exit(0);}



3.命名管道FIFO

特点:1.FIFO是作为一个特殊的设备文件存在;

2.不同祖先进程的进程之间可以共享数据;

3.使用完后FIFO将继续保存。

#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define FIFO "/tmp/myfifo"                                         //管道位置main(int argc,char** argv){	char buf_r[100];	int  fd;	int  nread;                                               		if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))       //创建并执行		printf("cannot create fifoserver\n");	printf("Preparing for reading bytes...\n");		memset(buf_r,0,sizeof(buf_r));	fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);                      //readonly 不阻塞	if(fd==-1)	{		perror("open");		exit(1);		}	while(1)	{		memset(buf_r,0,sizeof(buf_r));				if((nread=read(fd,buf_r,100))==-1){                //读取管道			if(errno==EAGAIN)				printf("no data yet\n");		}		printf("read %s from FIFO\n",buf_r);		sleep(1);	}		pause();	unlink(FIFO);}

通常对命名管道的读在写之前。

#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define FIFO_SERVER "/tmp/myfifo"main(int argc,char** argv)                               //argc:参数个数?    argv:参数{	int fd;	char w_buf[100];	int nwrite;		if(fd==-1)		if(errno==ENXIO)			printf("open error; no reading process\n");	fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);                           //writeonly,管道已在read中创建,可以直接打开。	if(argc==1)		printf("Please send something\n");	strcpy(w_buf,argv[1]);	if((nwrite=write(fd,w_buf,100))==-1)                                  //write	{		if(errno==EAGAIN)			printf("The FIFO has not been read yet.Please try later\n");	}	else 		printf("write %s to the FIFO\n",w_buf);}

FIFO创建后,可以用open(),close(),read(),write(),unlink()等流操作函数操作。