C 程序来演示 fork() 和 pipe()

2022-12-15 15:55:53 浏览数 (1)


开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

fork() 用于创建子进程。此子进程是原始(父)进程的副本。它是在类Unix操作系统上创建进程的主要方法。

语法:

代码语言:javascript复制
fork(); 
// 它不接受任何参数,而是返回整数值。它可以返回负、正或零整数值。

pipe():用于Linux中的进程间通信。这是一个系统功能。

语法:

代码语言:javascript复制
int pipe(int pipefd[2]);
C 程序来演示 fork() 和 pipe():

编写 Linux C 程序以创建两个进程 P1 和 P2。P1 获取一个字符串并将其传递给 P2。P2 将接收到的字符串与另一个字符串连接起来,而不使用字符串函数,并将其发送回 P1 进行打印。

例子:

代码语言:javascript复制
Other string is: forgeeks.org

Input  : www.haiyong
Output : www.haiyong.site
        
Input :  www.code.haiyong
Output : code.haiyong.site

解释:

  • 要创建子进程,我们使用 fork()。fork() 返回 :
    • <0 无法创建子(新)进程
    • =0 表示子进程
    • >0 即子进程到父进程的进程 ID。当 >0 时,将执行父进程。
  • pipe() 用于将信息从一个进程传递到另一个进程。pipe() 是单向的,因此,对于进程之间的双向通信,可以设置两个管道,每个方向一个。

例:

代码语言:javascript复制
int fd[2];
pipe(fd);
fd[0]; //-> 用于使用读端
fd[1]; //-> 用于使用写结束

父进程内部: 我们首先关闭第一个管道的读取端 (fd1[0]),然后通过管道的写入端 (fd1[1]) 写入字符串。现在,父进程将到子进程完成。在子进程之后,父进程将关闭第二个管道的写入端(fd2[1]),并通过管道的读取端(fd2[0])读取字符串。

内部子进程: Child 通过关闭管道的写入端 (fd1[1]) 来读取父进程发送的第一个字符串,读取后连接两个字符串并通过 fd2 管道将字符串传递给父进程并退出。

输入

代码语言:javascript复制
www.haiyong

C程序演示 forke() 和 pipe() 的使用

代码语言:javascript复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
    // 我们使用两个管道第一个管道从父级发送输入字符串第二个管道从子级发送连接字符串

    int fd1[2]; // 用于存放第一根管道的两端
    int fd2[2]; // 用于存放第二根管道的两端

    char fixed_str[] = "haiyong.site";
    char input_str[100];
    pid_t p;

    if (pipe(fd1) == -1) {
        fprintf(stderr, "Pipe Failed");
        return 1;
    }
    if (pipe(fd2) == -1) {
        fprintf(stderr, "Pipe Failed");
        return 1;
    }

    scanf("%s", input_str);
    p = fork();

    if (p < 0) {
        fprintf(stderr, "fork Failed");
        return 1;
    }

    // 父进程
    else if (p > 0) {
        char concat_str[100];

        close(fd1[0]); // 关闭第一根管道的读取端

        // 写入输入字符串并关闭第一个管道的写入端。
        write(fd1[1], input_str, strlen(input_str)   1);
        close(fd1[1]);

        // 等待孩子发送字符串
        wait(NULL);

        close(fd2[1]); // 关闭第二个管道的写入端

        // 从孩子身上读取字符串,打印并关闭阅读端。
        read(fd2[0], concat_str, 100);
        printf("Concatenated string %sn", concat_str);
        close(fd2[0]);
    }

    // 子进程
    else {
        close(fd1[1]); // 关闭第一个管道的写入端

        // 关闭first的写入端使用第一个管道读取字符串
        char concat_str[100];
        read(fd1[0], concat_str, 100);

        // 将固定字符串与其连接
        int k = strlen(concat_str);
        int i;
        for (i = 0; i < strlen(fixed_str); i  )
            concat_str[k  ] = fixed_str[i];

        concat_str[k] = ''; // 字符串以“”结尾

        // 关闭两个读取端
        close(fd1[0]);
        close(fd2[0]);

        // 写入连接字符串并关闭写入结束
        write(fd2[1], concat_str, strlen(concat_str)   1);
        close(fd2[1]);

        exit(0);
    }
}

输出:

代码语言:javascript复制
Concatenated string www.haiyong.site

0 人点赞