欢迎使用CSDN-markdown编辑器

来源:互联网 发布:业务建模与数据挖掘 编辑:程序博客网 时间:2024/05/16 06:09

Linux进程通讯主要有管道与有名管道、消息、文件流、信号、共享内存和套接字等方式。
前段时间主要学习了管道与有名管道、共享内存和套接字。
这里主要记录管道与有名管道的学习过程。
管道:管道是单向、FIFO的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写数据的进程从管道尾部写入数据,而读数据的进程则从管道头部读出数据,数据一旦读取,就会从管道中消失,其他进程无法再次读取该数据。管道提供堵塞机制,当进程在写数据进管道时,读数据的进程将会堵塞;当管道数据已经满时,写数据的进程将会堵塞。
清楚这些基本之后后,就主要是了解一些需要调用的函数。
(1)管道的创建:int pipe( int fd[2] )
返回值:当成功调用时,返回0,当调用失败时,返回-1。
其中fd[0]为读端口,fd[1]为写端口。
另外,还需要用到一些进程的函数
子进程的创建:pid_t fork( )
返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID,否则出错返回
这部分学习主要参考:http://blog.csdn.net/jason314/article/details/5640969
管道通讯是基于文件描述符工作的,因此需要使用read( )和write( )进行数据读写工作。
下面这段代码很清晰地表现出匿名管道的使用方式。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<unistd.h>int main(){    pid_t pid;    int fd[2];    int stat;    char buf[5] = "abc\n";    if(pipe(fd)){        printf("pipe failed!\n");        exit(0);    }    pid=fork();    switch(pid){        case -1:                printf("frok failed\n");                exit(0);        case 0:            close(fd[1]);            read(fd[0],buf,5);            printf("%s",buf);            exit(0);        default:            close(fd[0]);            write(fd[1],buf,5);            wait(&stat);            exit(0);    }    return 0;}

其中需要注意的是,pid=fork( ),当创建子进程时,子进程的pid=0,父进程的pid则为子进程的pid。当进入父进程时,进行写操作之后,调用wait( )函数。一旦调用,父进程便停止,等待直至子进程被销毁。

命名管道:由于匿名管道必须是在共同的祖先进程启动的进程间进行通讯,若要在没有任何关系的两个进程间进行通讯,可以采用命名管道的方式。而命名管道的机制与管道类似,但其间会多生成一个FIFO文件进行通讯。
(1)命名管道的创建:

int mkfifo(const char *filename, mode_t mode);int mknod(const char *filename, mode_t mode , dev_t dev);

其中,filename是fifo的文件名,mode指定fifo文件的权限。
若直接使用open( )对fifo文件进行读写操作,则可能会产生堵塞。

//send.c#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>int main(){    const char *filename = "fifo";    int fd;    int n,i;    char buf[10];    if(access(filename,F_OK)==-1)    {        n = mkfifo(filename,S_IFIFO|0666);        if(n!=0)        {            printf("create fail!");            exit(0);        }       }    if((fd = open(filename,O_WRONLY))==-1)    {        printf("open fail!");        exit(0);    }    while(1)    {        fgets(buf,10,stdin);        write(fd,buf,strlen(buf)+1);        memset(buf,'\0',10);    }    close(fd);}

在send.c中,先是创建fifo文件,然后直接打开fifo文件,并且对fifo文件进行写入操作。

//read.c#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>int main(){    const char *filename = "fifo";    int fd;    int i;    char buf[10];    if((fd = open(filename,O_RDONLY))==-1)    {        printf("open fail!");        exit(0);    }    while(1)    {        memset(buf,'\0',sizeof(buf));        read(fd,buf,10);        printf("the words you get:%s",buf);    }    close(fd);}

与send.c对应,read.c中只需要打开fifo文件并读取至缓存中,然后显示出来。
其中加入access(filename,F_OK)是为了防止重复创建fifo文件报错。以上两个程序都是以堵塞的方式进行数据传输。要使用非堵塞方式,只需要在read.c更改一下

fd = open(filename,O_RDONLY|O_NONBLOCK))==-1

管道对本机多进程通讯发挥着很重要的作用,形式简单,使用便利,传输速率较快,当数据量较小时应当使用管道方式。

0 0
原创粉丝点击