1. 程式人生 > >自測之Lesson10:管道

自測之Lesson10:管道

epo lesson stdlib.h ror 自測 stp send can child

題目:建立雙向管道,實現:父進程向子進程傳送一個字符串,子進程對該字符串進行處理(小寫字母轉為大寫字母)後再傳回父進程。

實現代碼:

#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:管道