Linux进程之间通信

2019-05-25  本文已影响0人  小小混世魔王

上篇文章了解到Linux平台下编译静态库和动态库并了解到链接的原理。https://www.jianshu.com/p/020b341d3c2b 这篇文章来了解一些进程方面的知识。
进程是程序运行的活动,是系统进行资源分配和调度的基本单位。简单的来看一个正在运行的程序就是一个进程。进程包含的数据有程序可运行机器码映像。映像加载到虚拟内存的 。内存的内容包括可运行代码、特定于进程的数据(输入、输出)、调用堆栈、堆栈(用于保存运行时运数中途产生的数据)。 分配给该进程的资源的操作系统描述符,如文件描述或文件句柄等。进程也类似线程存在状态的,由内核pcb进程控制块来控制进程的状态。

进程之间通信

为了安全系统设计进程之间的数据是不可以共享的,有时又需要访问另一个进程的数据。就需要进程之间的通信。
利用管道通信:
管道可以看成是一个特殊的文件,它不占磁盘空间,占用的是内存,所以我们直接可以read 和write数据。由于管道是半双工数据传输,数据只能单向流通,读写数据是不能够同时进行的。而且只限于有血缘关系(父子,兄弟进程)的进程之间的通信。
通过fork函数创建子线程看看他们是怎么通信的。

#include<stdio.h>
#include<unistd.h>

//父进程向子线程 写东西
int main() {
        int fd[2];
        int ret = pipe(fd);
        if(ret != 0) {
                printf("crate pipe fail\n");
                return -1;
        }
        pid_t pid = fork();
        if(pid < 0) {
                printf("fork process fail\n");
                return -1;
        } else if(pid == 0){
                sleep(2);
                printf("Im child process\n");
                close(fd[1]);
                char buf[11];
                read(fd[0],buf,11);
                printf("输出:%s",buf);
        }else{
                printf("Im parent process\n");
                close(fd[0]);
                write(fd[1],"hello world",11);
        }
        return 0;
}

信号:
进程之间可以通过信号来进行通信,信号是内核自带的传递携带数据量不大,一般携带一个数字作为处理的信号。在pcb进程控制块中包含有信号屏蔽字与未决信号集。信号的产生有系统调用kill , raise, abort等函数,包括硬件的异常,访问了非法内存等都会产生信号。信号的处理方式,系统可以忽略 捕获 执行系统默认活动,android应用出现异常退出系统接收到信息执行了默认的活动程序才退出的。包括进程的杀死的都是通过系统接收信号来执行的。pcb进程控制块中的信号屏蔽字是用来屏蔽某个型号的,一个型号发送是发送到pcb进程控制块中的未决信号集中的,系统执行信号时需要查看该信号是否屏蔽。
共享映射区:

共享映射区是基于文件来实现的,并不是普通的文件读写来通信的,普通的文件读写是要通过用户空间写入内核区,另一个进程读取需要从内核读取到用户的空间实现数据的通信,数据经历了两次拷贝。共享映射区通信方式只要通过一次数据的拷贝,而且还不要经过内核,用户空间进入内核是一个比较缓慢过程,不要轻易的进入内核。共享映射区的原理是通过虚拟内存映射一个文件的区域,通过操作映射的内存就能够操作文件。 共享映射区.png

看看具体的代码实现

写端
#include<stdio.h>
#include<unistd.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<string.h>
int main() {
        int fd = open("mmapipc",O_RDWR | O_CREAT | O_TRUNC, 0644);
        ftruncate(fd, 13);
        if(fd == -1) {
                printf("open fail \n");
                return -1;
        }
        char* writecontent =(char*) mmap(NULL,13,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        if(writecontent == MAP_FAILED) {

                printf("映射失败");
                return -1;
        }
        while(1){
                sleep(1);
                memcpy(writecontent, "hello", 5);
        }

        return 0;
}
   
读端
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/mman.h>
#include <fcntl.h>

int main(){
        char *pathname = "mmapipc";
        int fd = open(pathname,O_RDONLY);
        if(fd == -1) {

                printf("open file fail\n");
                return -1;
        }

        char* readIpc =(char*)mmap(NULL,11,PROT_READ, MAP_SHARED, fd, 0);

        if(readIpc == MAP_FAILED) {
                printf("open file fail\n");
                return -1;
        }

        while (1){
                printf("%s",readIpc);
        }

        return 0;
}

小结:

Linux进程之间的通信还有套接字的方式,这里不去了解,关于进程知识,包括怎么fork子进程,什么是孤儿进程,僵尸进程,守护进程,包括虚拟内存有兴趣可以了解了解。

上一篇下一篇

猜你喜欢

热点阅读