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通信是使用的最为广泛的进程间通信的方法, 它不仅可以在同一主机上的进程间通信, 还可以进行不同主机之间的通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux系统中,进程通信是指两个或多个进程之间交换信息或共享资源的过程。Linux提供了多种进程通信方式,包括管道、命名管道、信号、共享内存、消息队列、套接字等。下面简要介绍一下每种通信方式的特点: 1. 管道(Pipe):管道是一种半双工的进程通信方式,用于在两个进程之间传输数据。它可以是匿名管道或命名管道,匿名管道只能在具有亲缘关系的进程之间使用,而命名管道可以在任意两个进程之间使用。 2. 信号(Signal):信号是一种异步的进程通信方式,用于在进程之间传递信息。当一个进程向另一个进程发送信号时,接收进程会中断正在执行的程序,转而执行信号处理程序,处理完后再返回原来的程序。 3. 共享内存(Shared Memory):共享内存是一种高效的进程通信方式,用于在两个或多个进程之间共享内存区域。多个进程可以访问同一块内存区域,从而实现数据共享,但需要使用信号量等机制来控制进程之间对共享内存的访问。 4. 消息队列(Message Queue):消息队列是一种进程通信方式,用于在两个或多个进程之间传输消息。进程可以把消息发送到消息队列中,其他进程可以从队列中读取消息,消息队列提供了一种可靠的消息传递机制。 5. 套接字(Socket):套接字是一种通用的进程通信方式,可用于在本地进程之间或网络上的进程之间进行通信Linux将套接字视为一种特殊类型的文件,进程可以通过套接字进行文件读写操作,实现进程之间的通信。 不同的进程通信方式各有特点,应该根据实际情况选择合适的通信方式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值