天天看点

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

1,进程间通信的方式

1,管道

2,消息队列

3,共享内存

4,信号量

2.进程间通信目的:

1)数据传输:一个进程需要将它的数据发送给另一个进程

2)资源共享:多个进程之间共享同样的资源。

3)通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。

4)进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变

3,进程间通信发展

管道

System V进程间通信

POSIX进程间通信

4,进程间通信发展

管道

System V进程间通信

POSIX进程间通信

5,进程间通信分类

管道

匿名管道pipe

命名管道

System V IPC

System V 消息队列

System V 共享内存

System V 信号量

POSIX IPC

消息队列

共享内存

信号量

互斥量

条件变量

读写锁

进程间通信必须要看到一份公共资源,这里的资源应该属于谁?肯定是操作系统!

进程间通信的本质前提,也可能以队列的方式,也可能提供的就是原始的内存块,这也是通信方式有很多种的原因

管道

什么是管道:管道是Unix 中最古老的进程间通信的形式

我们把一个进程连接到另一个进程的一个数据流称为“管道”,为了方便我们理解如下图:

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

可以看出进程要相互通信需要一块公共资源,而管道就一个共享文件,具体通信方式如下图:

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
}
           
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

接下来我们看一下父子进程正常通信的情况,子进程写,父进程读。

#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
        if(fork() == 0)   //子进程
        {
                const char* buf = "hello 天下";
                close(pipefd[0]);
                write(pipefd[1],buf,strlen(buf));

                close(pipefd[1]);

                exit(1);

        }
        close(pipefd[1]);
        char buffer[64] = {0};
        read(pipefd[0],buffer,sizeof(buffer));
        printf("%s\n",buffer);
        close(pipefd[0]);

        int status = 0;
        waitpid(-1,&status,0);
        printf("exit code :%d\n",(status >> 8)& 0xFF);
        printf("exit signal: %d\n",status & 0x7F);
        //父进程

}
           
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

结论:管道是一个只能单向通信的的通信管道 。

接下来我们看一下子进程一直写,父进程5秒钟读一次;

#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
        if(fork() == 0)   //子进程
        {
                while(1)
                {

                        const char* buf = "hello 天下";
                        close(pipefd[0]);
                        write(pipefd[1],buf,strlen(buf));


                }
                        close(pipefd[1]);
                        exit(1);

        }

        close(pipefd[1]);

        while(1)
        {

                char buffer[64] = {0};
                read(pipefd[0],buffer,sizeof(buffer));
                printf("%s\n",buffer);
                sleep(5);
        }
        close(pipefd[0]);

        //int status = 0;
//      waitpid(-1,&status,0);
//      printf("exit code :%d\n",(status >> 8)& 0xFF);
//      printf("exit signal: %d\n",status & 0x7F);
        //父进程

}
           
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

结论: 管道是面向字节流的,子进程一直写“hello 天下”,父进程5秒读一次,但不是一次读5个“hello 天下”。

我们现在看一下管道文件多大:每次写一个字符,读端不读,直到写满。

#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
        if(fork() == 0)   //子进程
        {
                int count = 0;
                while(1)
                {

                        //const char* buf = "hello 天下";
                        char ch = 'a';
                        close(pipefd[0]);
                        write(pipefd[1],&ch,1);
                        ++count;
                        printf("%d\n",count);

                }
                        close(pipefd[1]);
                        exit(1);

        }

        close(pipefd[1]);

        while(1)
        {

        //      char buffer[64] = {0};
        //      read(pipefd[0],buffer,sizeof(buffer));
        //      printf("%s\n",buffer);
        //      sleep(5);
        }
        close(pipefd[0]);

        //int status = 0;
//      waitpid(-1,&status,0);
//      printf("exit code :%d\n",(status >> 8)& 0xFF);
//      printf("exit signal: %d\n",status & 0x7F);
        //父进程

}
           
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

最大是 65536字符,也就是4KB.

接下来我们在看4种情况:

a.读端不读或者读的慢,写段要等读端

b.读端关闭,写端收到SIGPIPE信号直到终止

c.写端不写或者写的慢,读端要等写端

d.写端关闭,读端读完pipe内部的数据然后在读,会读到0,表示读到文件结尾

1.读端不读或者读的慢,写段要等读端

#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
        if(fork() == 0)   //子进程
        {
                int count = 0;
                while(1)
                {

                        //const char* buf = "hello 天下";
                        char ch = 'a';
                        close(pipefd[0]);
                        write(pipefd[1],&ch,1);
                        ++count;
                        printf("%d\n",count);

                }
                        close(pipefd[1]);
                        exit(1);

        }

        close(pipefd[1]);

        while(1)
        {

                char buffer[64] = {0};
                read(pipefd[0],buffer,sizeof(buffer));
                printf("%c\n",buffer[0]);
                sleep(5);
        }
        close(pipefd[0]);

        //int status = 0;
//      waitpid(-1,&status,0);
//      printf("exit code :%d\n",(status >> 8)& 0xFF);
//      printf("exit signal: %d\n",status & 0x7F);
        //父进程

}
           

 写端写满了,读端一次读64个字符,但是写端并没有写入

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

 写端写满了,读端一次读1024 * 2个字符,但是写端写入

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

2.读端关闭,写端收到SIGPIPE信号直到终止

#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main()
{
        int pipefd[2];
        int ret = pipe(pipefd);
        if(ret < 0)
        {
                perror("pipe()");
        }
        printf("%d\n",pipefd[0]);
        printf("%d\n",pipefd[1]);
        if(fork() == 0)   //子进程
        {
                int count = 0;
                while(1)
                {

                        //const char* buf = "hello 天下";
                        char ch = 'a';
                        close(pipefd[0]);
                        write(pipefd[1],&ch,1);
                        ++count;
                        printf("%d\n",count);

                }
                        close(pipefd[1]);
                        exit(1);

        }

        close(pipefd[1]);

        while(1)
        {

                char buffer[1024*2] = {0};
                read(pipefd[0],buffer,sizeof(buffer));
                printf("%c\n",buffer[0]);
                sleep(5);
                close(pipefd[0]);
                exit(0);
        }

        int status = 0;
        waitpid(-1,&status,0);
        printf("exit code :%d\n",(status >> 8)& 0xFF);
        printf("exit signal: %d\n",status & 0x7F);
        //父进程

}
           
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端
进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

开始子进程和父进程一直在运行,到第五秒父进程退出,此时子进程也退出。

3.写端不写或者写的慢,读端要等写端

这种情况不做演示了。这个更正常情况是一样的。

4.d.写端关闭,读端读完pipe内部的数据然后在读,会读到0,表示读到文件结尾

进程间通信----管道1,进程间通信的方式4,信号量2.进程间通信目的:3,进程间通信发展4,进程间通信发展管道1.读端不读或者读的慢,写段要等读端

继续阅读