一、管道(先进先出)
1、创建管道
#include int pipe(int filed[2])
filed[0]是以读方式打开,filed[1]是以写方式打开
在同一个进程中使用管道是没有意义的,一般在创建管道后进程要调用fork,然后在父进程和子进程间进行通信。
管道中的数据容量是有限制的,/usr/include/linux/limits.h
PIPE_BUF = 4096
表明任一时刻管道中的数据量不能超过4096字节, 否则write会堵塞和直接返回0
例)
#include
#include
#include
int main()
{
int fd[2], nbytes;
pid_t childpid;
char string[] = "data from child process/n";
char readbuffer[32];
if(pipe(fd) < 0)
{
perror("pipe");
exit(1);
}
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(0 == childpid)
{//子进程
/*子进程关闭读管道*/
close(fd[0]);
/*向管道的写端口写入字符*/
wirte(fd[1], string, strlen(string));
exit(0);
}
else
{
/*父进程关闭写端口*/
close(fd[1]);
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
return 1;
}
二、使用管道的基本套路
1、创建管道;
2、调用fork,创建子进程;
3、在子进程中把管道文件描述符复制到标准输入或输出文件号,并关闭多余的文件描述符;
if(fork() == 0)
{
close(0);/*关闭标准输入文件描述符*/
dup(fd[0]);/*复制管道的输入端到标准输入*/
close(fd[0]);/*关闭多余的管道描述符*/
close(fd[1]);/*次处不使用管道的写入端*/
...
...
exit(0);
}
4、子进程exec其他应用程序
5、父进程也关闭一个多余的管道文件描述符;
6、父子进程读写管道;
7、父进程等待子进程终止。
三、可以使用popen代劳二的工作
#include
FILE * popen(const char * cmdstring, const char *type);
#include
int pclose(FILE *fp);
四、流管道(全双工管道), 可惜linux系统不支持
五、FIFO(命名管道)
两者之间的通信只要认可一个文件名既可,而不需要有集成关系
1、创建
#include
#include
int mkfifo(const char *pathname, mode_t mode);
2、打开
fopen("filename", "mode");
例)
//filo_s.c
int main()
{
int fdserver;
int fdclient;
pid_t cpid, spid;
char client_fifo_name[32];
mkfifo(SERVER_FIFO_NAME, 0660);
if((fdserver = open(SERVER_FIFO_NAME, O_RDWR)) == -1)
{
printf("Server:Can't open fifo/n");
fflush(stdout);
exit(1);
}
spid = getpid();
while(1)
{
/*读取客户进程pid并生成客户的FIFO文件名*/
read(fdserver, &cpid, sizeof(pid_t));/*阻塞,直到客户进程写入*/
sprintf(client_fifo_name, CLIENT_FIFO_NAME, cpid);
/*向客户fifo管道写入服务进程pid*/
if((fdclient = open(client_fifo_name, O_WRONLY)) == -1)
continue;
write(fdclient, &spid, sizeof(pid_t));
close(fdclient);
}
return 1;
}
//fifo_c.c
int main()
{
int fdserver;
int fdclient;
pid_t cpid, spid;
char client_fifo_name[32];
/*打开服务器FIFO管道*/
if((fdserver = open(SERVER_FIFO_NAME, O_WRONLY)) == -1)
{
printf("server not active/n");
exit(0);
}
/*创建并打开客户FIFO管道*/
cpid = getpid();
sprintf(client_fifo_name, CLIENT_FIFO_NAME, cpid);
mkfifo(client_fifo_name, 0660);
if((fdclient = open(client_fifo_name, O_RDWR)) == -1)
{
close(fdserver);
printf("can't open fifo/n");
exit(0);
}
/*写入自身pid,读出服务器pid*/
write(fdserver,&cpid, sizeof(pid_t));
/*阻塞,知道服务器进程写入*/
read(fdclient, &spid, sizeof(pid_t));
printf("client: get server pid :%d/n", spid);
close(fdserver);
close(fdclient);
unlink(client_fifo_name);
return 1;
}
六、System V IPC 消息队列、信号量、共享内存