进程通信:也就是我们所说的IPC,包括多种形式:管道,FIFO,消息队列,信号量,共享存储。其中管道和FIFO应用于大量应用程序。
管道
管道是UNIX系统IPC最古老的形式。但它有两种局限性:
1)它是半双工的,现在也有系统提供全双工的管道,但不利于移植。
2)管道只能在具有同一个祖先的两个进程间使用
管道创建
通过函数pipe创建
#include<unistd.h>
int pipe(int fd[2]);
成功返回0,出错返回-1
参数fd返回两个文件描述符:fd[0]为读,fd[1]为写。fd[1]的输出是fd[0]的输入。
通常在父进程中,调用pipe,然后fork一个子进程。如果想要从父进程向子进程写数据。则在父进程中关闭fd[0],在子进程关闭fd[1]。如果父进程从子进程读入数据,就进行相反的操作。
程序实例
额,头文件我加的有点多,并不需要。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stddef.h>
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/termios.h>
#include<sys/ioctl.h>
#include<pwd.h>
#include<setjmp>
int main(void)
{
int n;
int fd[2];
pid_t pid;
char line[200];
if(pipe(fd)<0) //创建管道
printf("err");
if((pid=fork())<0) //创建进程
printf("err");
else if(pid>0){ //在父进程中,关闭读管道,写数据到管道
close(fd[0]);
write(fd[1],"hello",sizeof(line));
}
else{ //在子进程中,关闭写管道,从管道中读数据,最后写至标准备输出
close(fd[1]);
n=read(fd[0],line,100);
write(STDOUT_FILENO,line,n);
}
exit(0);
}
函数popen和pclose
popen这个函数实现的是:创建一个管道,fork一个子进程,关闭未使用的管道端,执行一个shell命令。就是我们之前做的很多步,这一个函数就实现了。
#include<stdio.h>
FILE *popen(const char *cmdstring,const char *type);
成功返回文件指针,出错返回NULL
int pclose(FILE *fp)
成功返回cmdstring的终止状态,出错返回-1
type参数:"r"表示父进程从管道读,"w"表示父进程从管道写
cmdstring:shell命令,包括我们程序编译的可执行文件
程序实例
#include<unistd.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/termios.h>
#include<sys/ioctl.h>
#include<pwd.h>
#include<setjmp.h>
#include<time.h>
#include<pthread.h>
#include<sys/wait.h>
#include<ctype.h>
int main()
{
char line[1000];
FILE *fpin;
if((fpin=popen("ls -l","r"))==NULL) //从管道读取ls 输出的数据到文件fpin
printf("popen err\n");
for(;;){
if(fgets(line,1000,fpin)==NULL) //从文件fpin中读取数据到line
break;
if(fputs(line,stdout)==EOF)
printf("fputs err\n"); //将读取的数据输出到标准输出流
}
if(pclose(fpin)==-1) //关闭I/O文件
printf("close error\n");
putchar('\n');
exit(0);
}