pipe管道

#Linux #FuzzerDevelop

在造轮子过程中有时候会遇到一个场景,一个模块生产资料,一个模块用来消费这些资料,我们想实现一个持续化的一个过程,不至于生成10000件之后停下来再去执行,有几种办法

  1. 多线程
  2. 异步
  3. 管道
  4. celery等框架
    这种参数pipe管道这种用法,AFL中也大量运用到了管道

管道的基本概念和使用方法

管道是一种进程间通信机制,它可以将一个进程的输出直接传递给另一个进程的输入,从而实现进程间的数据传输。

  1. 管道的创建:
    在Linux系统中,可以使用pipe()系统调用来创建一个管道。该系统调用会创建一个只有两个文件描述符的文件描述符数组,其中·fd[0]表示管道的读端,fd[1]表示管道的写端。在创建管道后,我们可以使用fork()系统调用来创建一个子进程,然后在父子进程之间通过管道进行通信。

  2. 管道的读写操作:
    在Linux系统中,可以使用read()系统调用从管道中读取数据,使用write()系统调用向管道中写入数据。当我们在一个进程中向管道写入数据时,另一个进程就可以使用read()系统调用来读取这些数据。

  3. 管道的使用场景:
    管道通常用于将一个进程的输出传递给另一个进程的输入,从而实现进程间的数据传输。在Linux系统中,我们可以使用管道来实现一些常见的功能,例如:

需要注意的是,管道有一定的缓冲区大小,如果写入的数据超过了缓冲区大小,就会导致阻塞。因此,在使用管道时需要注意缓冲区的大小和数据传输的速度。

  1. 管道的关闭:
    在使用管道时,需要在适当的时候关闭管道的读端和写端,以避免资源浪费和错误的数据传输。可以使用close()系统调用来关闭管道的读端和写端。

综上所述,管道是一种进程间通信机制,可以将一个进程的输出直接传递给另一个进程的输入,从而实现进程间的数据传输。在使用管道时需要注意缓冲区的大小和数据传输的速度,以及关闭管道的读端和写端。管道在Linux系统中有广泛的应用,是 Linux 下进程间通信的重要方式之一。

进程间通信基本原理

进程间通信(IPC)是操作系统中的一个重要概念,它允许不同进程之间进行数据交换和共享资源,从而实现协作和协同工作。下面介绍进程间通信的基本原理:

  1. 进程与进程之间是隔离的:
    在操作系统中,每个进程都有自己的虚拟地址空间和独立的资源,不同进程之间是隔离的,不能直接访问对方的资源。因此,为了实现进程间通信,需要通过一些特殊的机制来进行数据交换和共享。

  2. 进程间通信的方式:
    在操作系统中,常用的进程间通信方式包括管道、共享内存、消息队列、信号量、套接字等。这些通信方式都有各自的优缺点和适用范围,可以根据不同的需求来选择合适的通信方式。

  3. 进程间通信的基本原理:
    进程间通信的基本原理是通过操作系统内核来进行数据交换和共享。当一个进程需要与另一个进程进行通信时,它需要向操作系统内核发出请求,并提供相应的参数和数据。操作系统内核会根据请求的类型和参数来进行相应的处理,从而实现进程间的数据交换和共享。

  4. 进程间通信的实现方式:
    进程间通信的实现方式通常涉及到多个系统调用和库函数,这些函数包括创建进程、发送消息、接收消息、锁定资源、解锁资源等。在使用这些函数时,需要注意线程安全、死锁、竞争条件等问题,以确保程序的正确性和性能。

综上所述,进程间通信是操作系统中的一个重要概念,它允许不同进程之间进行数据交换和共享资源,从而实现协作和协同工作。进程间通信的实现方式通常涉及到多个系统调用和库函数,需要注意线程安全、死锁、竞争条件等问题。

多进程编程相关

多进程编程是指在操作系统中同时运行多个进程,并且这些进程可以通过一些机制进行通信、同步和互斥。下面介绍一些多进程编程技巧:

  1. 进程的创建:
    在Linux系统中,可以使用fork()函数来创建新进程。fork()函数会在当前进程的地址空间中创建一个新进程,并且将当前进程中的所有内容复制到新进程中。新进程会从fork()函数的返回值中得到一个0值,父进程会得到子进程的进程ID。

  2. 进程间通信:
    进程间通信是多进程编程中的一个重要方面。在Linux系统中,可以使用管道、消息队列、共享内存、信号量等机制进行进程间通信。其中,管道是最简单和常用的进程间通信方式,它可以将一个进程的输出直接传递给另一个进程的输入。共享内存是一种高效的进程间通信方式,它可以让多个进程共享同一块物理内存。

  3. 进程同步和互斥:
    在多进程编程中,需要进行进程同步和互斥,以避免多个进程同时访问共享资源时出现竞争条件和数据不一致的问题。在Linux系统中,可以使用信号量、互斥锁、条件变量等机制进行进程同步和互斥。互斥锁是一种简单的进程同步机制,它可以确保只有一个进程可以访问共享资源。条件变量是一种高级的进程同步机制,它可以让进程在特定的条件下等待或唤醒。

  4. 进程的终止:
    在多进程编程中,需要注意进程的终止问题。在Linux系统中,可以使用exit()函数来终止一个进程,也可以使用kill()函数向另一个进程发送终止信号。在进程终止时,需要确保释放所有的资源,包括文件描述符、共享内存和信号量等。

综上所述,多进程编程是一种重要的编程技巧,需要掌握进程的创建、进程间通信、进程同步和互斥等机制。在编写多进程程序时,需要注意进程的终止问题,以确保程序的正确性和性能。

案例

  1. 父进程向子进程发送数据,子进程将数据转换为大写并返回给父进程;
  2. 父进程向子进程发送数据,子进程将数据写入文件中;
  3. 父进程读取文件中的数据,将数据传递给子进程,子进程统计数据中的单词数并返回给父进程。
#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<sys/wait.h>
#define BUFFER_SIZE 1024

int main(){
    int fd1[2],fd2[2];
    pid_t pid;
    char buf[BUFFER_SIZE];
    if(pipe(fd1)<0||pipe(fd2)<0){
        perror("pipe error");
        exit(EXIT_FAILURE);
    }
    if((pid=fork())<0){
        perror("fork error");
        exit(EXIT_FAILURE);
    }
    if(pid==0){
        close(fd1[1]);
        close(fd2[0]);
        int n=0;
        n=read(fd1[0],buf,BUFFER_SIZE);
        for(int i=0;i<n;i++){
            buf[i]=toupper(buf[i]);
        }
        write(fd2[1],buf,n);
        close(fd1[0]);
        close(fd2[1]);
        exit(EXIT_SUCCESS);
    }
    else{
        close(fd1[0]);
        close(fd2[1]);
        printf("请输入传输数据:\n");
        fgets(buf,BUFFER_SIZE,stdin);
        write(fd1[1],buf,BUFFER_SIZE);
        wait(NULL);
        read(fd2[0],buf,BUFFER_SIZE);
        printf("转换后的数据为:%s\n",buf);
        close(fd1[1]);
        close(fd2[0]);
        exit(EXIT_SUCCESS);
    }

}

中间犯了一个错误,只声明了一个fd[2]数组,父子进程对一个buffer修改,导致父进程并没有接收到正确的子进程修改的数据,因为父子进程有各自的内存空间,因此需要通过管道进程通信