linux下编程——操作系统——管道通信

相关知识:

1、有名管道

一个可以在文件系统中长期存在的、具有路径名的文件。用系统调用mknod( )建立。它克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信。因而其它进程可以知道它的存在,并能利用路径名来访问该文件。对有名管道的访问方式与访问其他文件一样,需先用open( )打开。

2、无名管道

一个临时文件。利用pipe( )建立起来的无名文件(无路径名)。只用该系统调用所返回的文件描述符来标识该文件,故只有调用pipe( )的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信。当这些进程不再使用此管道时,核心收回其索引结点。

3、pipe文件的建立

分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符

4、读/写进程互斥

内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。

为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项。因此,每次进程在访问pipe文件前,都需检查该索引文件是否已被上锁。若是,进程便睡眠等待,否则,将其上锁,进行读/写。操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。

1、pipe( )

建立一无名管道。

系统调用格式

pipe(filedes)

参数定义

int pipe(filedes);

int filedes[2];

其中,filedes[1]是写入端,filedes[0]是读出端。

该函数使用头文件如下:

#include <unistd.h>

#inlcude <signal.h>

#include <stdio.h>

2read( )

系统调用格式

read(fd,buf,nbyte)

功能:从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。如该文件被加锁,等待,直到锁打开为止。

参数定义

int read(fd,buf,nbyte);

int fd;

char *buf;

unsigned nbyte;

3write( )

系统调用格式

read(fd,buf,nbyte)

功能:把nbyte 个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中。如文件加锁,暂停写入,直至开锁。

参数定义同read( )。

无名管道程序源码:

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int pid1,pid2;
 
int main()
{ 
    int fd[2];
    char outpipe[100],inpipe[100];
    pipe(fd);                       /*创建一个管道*/
    while ((pid1=fork()) == -1);
    if(pid1 == 0)
    {
        lockf(fd[1],1,0);
        sprintf(outpipe,"I am a child 1 "); 
        /*把串放入数组outpipe中*/
        write(fd[1],outpipe,50);     /*向管道写长为50字节的串*/
        sleep(1);                 /*自我阻塞5秒*/
        lockf(fd[1],0,0);
        exit(0);
    }
    else
    {
        sleep(1);//延时等待子进程1结束
        while((pid2=fork()) == -1);
        if(pid2 == 0)
        {    
            
            lockf(fd[1],1,0);           /*互斥*/
               sprintf(outpipe,"I am a child 2 ");
                write(fd[1],outpipe,50);
                sleep(1);
               lockf(fd[1],0,0);
                exit(0);
        }
        else
        {
            wait(0);              /*同步*/
             read(fd[0],inpipe,50);   /*从管道中读长为50字节的串*/
                printf("%s\n",inpipe);
             wait(0);
             read(fd[0],inpipe,50);
             printf("%s\n",inpipe);
                exit(0);
        }
    }
}

有名管道程序源码:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
int pid1,pid2;

int main()
{
    char *filename = "fifo";
    int res = mkfifo(filename,0666);//创建文件
    if(res < 0)
    {
        perror("mkfifo error");
        return -1;
    }

    int fd = open(filename,O_RDWR);//打开文件
    if(fd < 0)
    {
        perror("open error");
        return -2;
    }

    while((pid1=fork()) == -1);//创建子进程1
    if(pid1 == 0)
    {
        char *str1 = "I am a child 1";
        int len1 = write(fd,str1,strlen(str1));
    }
    else
    {
        sleep(1);//等待子进程1结束
        while((pid2=fork()) == -1);
        if(pid2 == 0)
        {
            char *str2 = "   I am a child 2";
            int len2 = write(fd,str2,strlen(str2));
        }
        else 
        {
            wait(0);
            wait(0);
            int len;
            char buf[128] = {0};
            len = read(fd,buf,sizeof(buf) - 1);
            printf("%s\n",buf);

        }
    }
    
    close(fd);
    unlink(filename);
}