实现linux 中c 函数popen( ),pclose( ); 进程通信、匿名管道


my_popen(), my_pclose()代码

my_popen.c

#include "head.h"

static pid_t *childpid = 0;
static int maxsize = 0;

FILE *my_popen(const char *cmd, const char *type) {
    FILE *fp;
    int pipefd[2];
    pid_t pid;

    if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) {
        errno = EINVAL;
        return 0;
    }

    if (!childpid) {
        maxsize = sysconf(_SC_OPEN_MAX);
        printf("maxsize = %d\n", maxsize);
        if (!(childpid = (pid_t *)calloc(maxsize, sizeof(pid_t)))) {
            return 0;
        }
    }
    if (pipe(pipefd) < 0) return 0;

    if ((pid = fork()) < 0) return 0;

    if (!pid) {
        if (type[0] == 'r') {
            close(pipefd[0]);
            if (pipefd[1] != STDOUT_FILENO) {
                dup2(pipefd[1], STDOUT_FILENO);
                close(pipefd[1]);
            }
        } else {
            close(pipefd[1]);
            if (pipefd[0] != STDIN_FILENO) {
                dup2(pipefd[0], STDIN_FILENO);
                close(pipefd[0]);
            }
        }
        execl("/bin/sh", "sh", "-c", cmd, NULL);
    }

    if (type[0] == 'r') {
        close(pipefd[1]);
        if ((fp = fdopen(pipefd[0], type)) == 0) {
            return 0;
        }
    } else {
        close(pipefd[0]);
        if ((fp = fdopen(pipefd[1], type)) == 0) {
            return 0;
        }
    }
    childpid[fileno(fp)] = pid;
    return fp;
}

int my_pclose(FILE *fp) {
    int status, pid, fd;
    fd = fileno(fp);
    pid = childpid[fd];
    if (!pid) {
        errno = EINVAL;
        return -1;
    }
    fflush(fp);
    close(fd);
    wait4(pid, &status, WUNTRACED, 0);
    return status;
}

head.h

#ifndef _HEAD_H
#define _HEAD_H
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 #include 
#include 
#include 
#include 
#include 
#include 

#include "my_popen.h"
#endif

my_popen.h

#ifndef _MY_POPEN_H
#define _MY_POPEN_H
FILE *my_popen(const char *cmd, const char *type);
int my_pclose(FILE *fp);
#endif