码迷,mamicode.com
首页 > 系统相关 > 详细

进程间通信

时间:2019-05-01 11:59:56      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:inter   文件   for   set   缓冲   png   exit   管道   ring   

1.管道

技术图片

 

对于具有公共祖先的进程,其管道是建立在3-4G的内核空间中的。每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

技术图片

技术图片

 

调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);向这个文件读写数据其实是在读写内核缓冲区。pipe函数调用成功返回0,调用失败返回-1。

#include <sys/wait.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>                                                           
#include<stdlib.h>
#include<string.h>
int main(void)
{
    pid_t pid; 
    int fd[2];
    if(pipe(fd)<0)
    {
        perror("pipe");
        exit(1);
    }
    printf("fd[0]=%d, fd[1]= %d\n",fd[0],fd[1]);
    if((pid=fork())<0)
        {
            perror("fork");
            exit(1);
        }
    else if(pid==0)//child
    {
        char c_str[1024];
        int n;
        close(fd[1]);//关闭写端口
        n=read(fd[0],c_str,sizeof(c_str)/sizeof(c_str[0]));//由于不知道读多少,所以读取最大长度
        close(fd[0]);
        write(STDOUT_FILENO,c_str,n);
    }
    else//parents
    {
        char str[]="hello pipe!\n";
        sleep(2);
        close(fd[0]);//关闭读端口
        write(fd[1],str,strlen(str));
        close(fd[1]);
        wait(NULL);//等待回收子进程资源
    }
    return 0;
}

技术图片

 

在父进程没有传输数据在管道中时,子进程中的read函数会阻塞等待。我们可以使用fcntl函数改变一个已经打开文件的属性,如重新设置读、写、追加、非阻塞等标志。

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>                                                           
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>
int main(void)
{
    pid_t pid; 
    int fd[2];
    if(pipe(fd)<0)
    {
        perror("pipe");
        exit(1);
    }
    printf("fd[0]=%d, fd[1]= %d\n",fd[0],fd[1]);
    if((pid=fork())<0)
        {
            perror("fork");
            exit(1);
        }
    else if(pid==0)//child
    {
        char c_str[1024];
        int n,flags;
        flags=fcntl(fd[0],F_GETFL);
        flags |=O_NONBLOCK;
        if(fcntl(fd[0],F_SETFL,flags)==-1)
        {
            perror("fcntl");
            exit(1);
        }
        close(fd[1]);//关闭写端口
tryagain:
        n=read(fd[0],c_str,sizeof(c_str)/sizeof(c_str[0]));//由于不知道读多少,所以读取最大长度
        if(n<0)
        {
            if(errno==EAGAIN)
            {
                write(STDOUT_FILENO,"try again...\n",13);
                sleep(1);
                goto tryagain;
            }
            perror("read");
            exit(1);
        }
        close(fd[0]);
        write(STDOUT_FILENO,c_str,n);
    }
    else//parents
    {
        char str[]="hello pipe!\n";
        sleep(2);
        close(fd[0]);//关闭读端口
        write(fd[1],str,strlen(str));
        close(fd[1]);
        wait(NULL);//等待回收子进程资源
    }
    return 0;
}

技术图片

此时,read已经不再是阻塞了。需要注意的是,使用管道技术,应该在fork之前创建管道。

 

2.FIFO

 

进程间通信

标签:inter   文件   for   set   缓冲   png   exit   管道   ring   

原文地址:https://www.cnblogs.com/yangguang-it/p/10799409.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!