LINUX 下进程的通信方式

在LINUX系统下, 提供了多种进程间的通信方式,在系统里面能够灵活的运用这些方式, 可以很方便的实现一些功能, 达到事倍功半的效果。

在LINUX下, 通常可以通过fork或者system产生的新的进程, 每一个进程都有一个进程ID来标识该进程。

pipe通信

无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

  • 函数原型
    int pipe(int filedes[2]);
  • 函数说明
    pipe()会建立管道,并将文件描述词由参数filedes数组返回。
    filedes[0]为管道里的读取端
    filedes[1]则为管道的写入端。

  • 返回值:
    若成功则返回零,否则返回-1,错误原因存于errno中。
    错误代码:
    EMFILE 进程已用完文件描述词最大量
    ENFILE 系统已无文件描述词可用。
    EFAULT 参数 filedes 数组地址不合法。

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

int main( void )
{
    int filedes[2];
    char buf[80];
    pid_t pid;

    pipe( filedes );
    printf("create one pipe: read_id:%d, write_id:%d\n", filedes[0], filedes[1]);
    pid=fork();
    if (pid > 0)
    {
        printf( "\nParent process %d, child proces: %d,here write a string to the pipe.\n", getppid(),pid);
        char s[] = "Hello world , this is write by pipe.\n";
        write( filedes[1], s, sizeof(s) );
        printf("write one string:%s into write_id:%d\n", s, filedes[1]);
        close( filedes[0] );
        close( filedes[1] );
    }
    else if(pid == 0)
    {
        printf( "\nChild process %d,here read a string from the pipe.\n", getpid());
        read( filedes[0], buf, sizeof(buf) );
        printf( "read one string:%s from read_id:%d\n", buf, filedes[0]);
        close( filedes[0] );
        close( filedes[1] );
    }
}

popen 通信

popen() 函数用于创建一个管道:其内部实现为调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程这个进程必须由 pclose() 函数关闭。

  • 函数原型:
      #include “stdio.h”
      FILE popen( const char command, const char* mode )

  • 参数说明:
      command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用 -c 标志,shell 将执行这个命令。
      mode: 只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到 command 的标准输入。

  • 返回值:
      如果调用成功,则返回一个读或者打开文件的指针,如果失败,返回NULL,具体错误要根据errno判断;
      

#include<stdio.h> 

int main(void) { 
    FILE *fp = NULL; 
    char buf[10240] = {0}; 

    fp = popen("ls -al","r"); 
    if(fp == NULL){ 
        return 0; 
    } 
    fread(buf, 10240, 1, fp); 
    printf("%s\n",buf); 
    pclose(fp); 
    return 0; 
}

命名管道(FIFO)

FIFO代表先进先出,但它是一个单向数据流,也就是半双工,和管道不同的是:每个FIFO都有一个路径与之关联,从而允许无亲缘关系的进程访问。

  • 函数原型
    int mkfifo(const char * pathname,mode_t mode);
  • 函数说明
    mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此 umask值也会影响到FIFO文件的权限。Mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开 FIFO文件时,O_NONBLOCK旗标会有影响
    1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。
    2、没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。
  • 返回值
    若成功则返回0,否则返回-1,错误原因存于errno中。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

int main( int argc, char **argv )
{
    mode_t mode = 0666;
    const char* fifo_path = "/tmp/fifo_test";
    char* message = "Hello mkfifo message";
    int fd_read, fd_write;
    char buf[100] = {0};

    if (mkfifo( fifo_path, mode)<0 )
    {
        printf( "mkfifo err");
        return -1;
    }
    printf("create fifo success.\n");



    fd_write = open(fifo_path, "w+");
    if (fd_write < 0) {
        printf("open fifo write  fail\n");
        return -1;
    }
    if (write(fd_write,  message, strlen(message)+1) < strlen(message)+1) {
       printf("write message err");
       return -1;
    }
    fd_read = open(fifo_path, "r");
    if (fd_read < 0) {
        printf("open fifo read fail\n");
        return -1;
    }

    while (1) {
            if (read(fd_read, buf, 100) != -1 ) {
                printf("read fifo message error\n");
                return -1;
            }
    }

    printf("success read message:%s\n", buf);
    return 0;
}

消息队列通信

请参考: https://www.cnblogs.com/caolicangzhu/p/6985278.html

信号量通信

信号量(semophore )是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
请参考: https://blog.csdn.net/u014338577/article/details/53157124

信号通信

进程间的信号通信, 是进程进通信比较常用的方式, 通过发送信号, 在进程之间通信。
请参考:http://kmoving.blog.163.com/blog/static/205049197201222885035422/

共享内存通信

共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
请参考:https://blog.csdn.net/ljianhui/article/details/10253345

socket 通信

socket通信是使用的最为广泛的进程间通信的方法, 它不仅可以在同一主机上的进程间通信, 还可以进行不同主机之间的通信。

猜你喜欢

转载自blog.csdn.net/baijiwei/article/details/79677093
今日推荐