自测之Lesson10:管道

Posted GGBeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自测之Lesson10:管道相关的知识,希望对你有一定的参考价值。

题目:建立双向管道,实现:父进程向子进程传送一个字符串,子进程对该字符串进行处理(小写字母转为大写字母)后再传回父进程。

 

实现代码:

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

void TestPipeDouble()
{
        pid_t pid;
        int fd_A[2], fd_B[2];
        if (pipe(fd_A) || pipe(fd_B)) {         // 创建管道A和管道B
                perror("pipe fail");
                return;
        }
        char szBuf[1024];
        pid = fork();
        if (pid == 0) {
                close(fd_A[1]);
                close(fd_B[0]);
                printf("Child pid:%d\n", getpid());
                while(1) {
                        memset(szBuf, 0, 1024);
                        read(fd_A[0], szBuf, 1024);
                        int i;
                        for (i = 0; i < strlen(szBuf); ++i) {
                                if (szBuf[i] <= ‘z‘ && szBuf[i] >= ‘a‘) {
                                        szBuf[i] += (‘A‘ - ‘a‘);
                                }
                        }
                        write(fd_B[1], szBuf, strlen(szBuf));
                }
                close(fd_A[0]);
                close(fd_B[1]);
        }
        else {
                close(fd_A[0]);
                close(fd_B[1]);
                printf("Father pid:%d\n", getpid());
                while(1) {
                        usleep(1000);
                        printf("Send:");
                        scanf("%s", szBuf);
                        write(fd_A[1], szBuf, strlen(szBuf));
                        memset(szBuf, 0, 1024);
                        read(fd_B[0], szBuf, 1024);
                        printf("Recv:%s\n", szBuf);
                }
                close(fd_A[1]);
                close(fd_B[0]);
        }

}


int main()
{
        TestPipeDouble();
        return 0;
}

 

 

题目:基于管道,并借助于dup2、exec函数族,实现命令“ps -ef | grep pipe”。

 

实现代码:

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


// 相当于“ps -ef | grep pipe”
void TestPipeRedir()            // 重定向
{
        int fd[2];
        pid_t pid;
        if(pipe(fd) == -1) {
                perror("pipe failed");
                return;
        }
        pid = fork();
        if (pid == 0) {
                dup2(fd[1], STDOUT_FILENO);     // 将本应输出至stdout的“ls -l”,转而输出至管道写端
                close(fd[0]);
                close(fd[1]);
                execlp("ps", "ps", "-ef", NULL);        // 参数列表以NULL结尾
        }
        else {
                dup2(fd[0], STDIN_FILENO);      // grep本应由stdin读入“ls -l”, 转而从管道读端读入
                close(fd[0]);
                close(fd[1]);
                execlp("grep", "grep", "pipe", NULL);
        }
}

int main()
{
        TestPipeRedir();
        return 0;
}

 

题目:使用popen函数实现命令“ps -ef | grep pipe”。

 

实现代码:

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

/* 使用sort对数组arr进行排序 */
void TestPipePopen_easy()
{
        int arr[] = {2, 3, 7, 3, 5, 10, 9};
        FILE *pFile = popen("sort -n", "w");    // 当前进程将arr传入子进程sort
        int i;
        for (i = 0; i != sizeof(arr) / sizeof(int); i++) {
                fprintf(pFile, "%d\n", arr[i]); // 父进程通过pFile来发送数据至子进程
        }
        pclose(pFile);                          // 一旦pclose,即开始执行sort命令
}

/* 实现命令ps -ef | grep pipe  */
void TestPipePopen_complex()
{
        FILE *pRead = popen("ps -ef", "r");             // 子进程ps将数据写入当前进程
        FILE *pWrite = popen("grep pipe", "w");         // 当前进程将数据写入子进程grep
        char szBuf[1024];
        while(fgets(szBuf, 1024, pRead))                // 逐行读取
        {
                fputs(szBuf, pWrite);

        }
        pclose(pRead);
        pclose(pWrite);
}

int main()
{
        TestPipePopen_easy();
        TestPipePopen_complex();
        return 0;
}

  

 

以上是关于自测之Lesson10:管道的主要内容,如果未能解决你的问题,请参考以下文章

自测之Lesson15:TCP&UDP网络编程

自测之Lesson6:低级I/O库

自测之Lesson11:消息和消息队列

Java学习lesson 05

[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础

使用 FFmpeg 通过管道输出视频片段