进程间通信(一)
1.为什么需要进程间通信?
① 数据转移
一个进程需要它的数据发送给另一个进程
② 资源共享
多进程之间共享同样的资源
③ 通知事件
一个进程需要想另一个或一组进程发送消息,通知他们发生了什么事件
④ 进程控制
一个进程控制另一个进程的执行
一.管道通信
管道定义:
管道是单向的,先进先出的,它把一个进程的输出和另一个进程的输出连接在一起,一个进程(写进程)在管道尾部写入数据,另一个进程(读进程)从管道头部读出数据。
管道分类:
无名管道: 用与父进程和子进程之间的通信
有名管道: 用于运行于同一系统中任意两进程间的通信
无名管道:
int pipe(int filedis[2]):
创建无名管道,管道建立时,它会创建两个文件描述符,
filedis[0] 用于读管道;filedis[1] 用于写管道
关闭管道只需要将这两个文件描述符关闭即可,用close逐个关闭
例:
#include <stdio.h>
#include <errno.h> //---------关于errno.h看这
http://www.cnblogs.com/riky/archive/2008/02/02/1062750.html
#include <unistd.h>
#include <stdlib.h>
int main(
void)
{
int pipe_fd[
2]
if (pipe(pipe_fd) <
0)
{
printf(
"
pipe creat error!\n
");
return -
1;
}
else
printf(
"
pipe creat success!\n
");
close (pipe_fd[
0]);
close (pipe_fd[
1]);
}
注意:必须要在系统调用fork之前调用pipe(),否则子进程将不会继承文件描述符
例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
int main(
void)
{
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 creat 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 form 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 write Hello!\n
");
if (write(pipe_fd[
1],
"
Pipe
",
5) != -
1)
printf(
"
parent write Pipe!\n
");
close(pipe_fd[
1]);
sleep(
3);
waitpid(pid,NULL,
0);
exit(
0);
}
}
下面是写
命名管道:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname,mode_t mode);
pathname: FIFO文件名
mode:属性(同文件操作)
创建了FIFO,就可以用OPEN打开它,一般的文件访问函数(close,read,write等)都可用于FIFO 。
当打开FIFO时,非阻塞标志(O_NONBLOCK)将对以后读写产生的影响:
1· 没有使用O_NONBLOCK:访问要求无法满足时,进程阻塞,如试图读取空的FIFO,将导致进程阻塞。
2·使用O_NONBLOCK: 访问要求无法满足时,不发生阻塞,立刻返回,errno是ENXIO。
例:
这个是读 :
/*
********* *********
********* fifo_read.c *********
********* *********
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <
string.h>
#define FIFO "/home/scrat/code/myfifo"
int main(
int argc,
char **argv)
{
char buf_r[
100];
int fd;
int nread;
//
创建管道
if ((mkfifo(FIFO,O_CREAT|O_EXCL) <
0) && (errno != EEXIST))
printf(
"
prepraing for reading bytes ~~~~~
");
//
打开管道
fd = open(FIFO,O_RDONLY|O_NONBLOCK,
0);
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 form FIFO\n
",buf_r);
sleep(
1);
}
pause();
//
暂停,等待
unlink(FIFO);
//
删除文件FIFO
}
下面这个是写:
/*
********* *********
********* fifo_write.c *********
********* *********
*/
#include <stdio.h>
#include <stdlib.h>
#include <
string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define FIFO_SERVER "/home/scrat/code/myfifo"
int main(
int argc,
char ** argv)
{
int fd;
char w_buf[
100];
int nwrite;
//
打开管道
fd = open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,
0);
if (argc ==
1)
{
printf(
"
Please send something\n
");
exit(-
1);
}
strcpy(w_buf,argv[
1]);
//
向管道写入数据
if ((nwrite = write(fd,w_buf,
100)) == -
1)
{
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);
return
0;
}