Last active
October 24, 2023 10:11
-
-
Save sasakiyudai/f7cb5ccc5cd85ae7f23d37748bfb1cfa to your computer and use it in GitHub Desktop.
Implementation of Multiple pipes in C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
// just count number of commands | |
int count(char ***cmd) { | |
int i; | |
i = 0; | |
while (cmd[i]) i++; | |
return i; | |
} | |
void pipeline(char ***cmd) { | |
int i, j = 0; | |
pid_t pid; | |
int cmd_len = count(cmd); | |
int fd[2 * cmd_len]; | |
// pipe(2) for cmd_len times | |
for (i = 0; i < cmd_len; i++) { | |
if (pipe(fd + i * 2) < 0) { | |
perror("couldn't pipe"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
while (*cmd != NULL) { | |
if ((pid = fork()) == -1) { | |
perror("fork"); | |
exit(1); | |
} else if (pid == 0) { | |
// if there is next | |
if (*(cmd + 1) != NULL) { | |
if (dup2(fd[j + 1], 1) < 0) { | |
perror("dup2"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
// if there is previous | |
if (j != 0) { | |
if (dup2(fd[j - 2], 0) < 0) { | |
perror("dup2"); | |
exit(EXIT_FAILURE); | |
} | |
} | |
for (i = 0; i < 2 * cmd_len; i++) { | |
close(fd[i]); | |
} | |
if (execvp((*cmd)[0], *cmd) < 0) { | |
perror((*cmd)[0]); | |
exit(EXIT_FAILURE); | |
} | |
} else if (pid < 0) { | |
perror("error"); | |
exit(EXIT_FAILURE); | |
} | |
// no wait in each process, | |
// because I want children to exec without waiting for each other | |
// as bash does. | |
cmd++; | |
j += 2; | |
} | |
// close fds in parent process | |
for (i = 0; i < 2 * cmd_len; i++) { | |
close(fd[i]); | |
} | |
// wait for children | |
for (i = 0; i < cmd_len; i++) wait(NULL); | |
} | |
int main(int argc, char *argv[]) { | |
char *ls[] = {"ls", NULL}; | |
char *rev[] = {"rev", NULL}; | |
char *nl[] = {"nl", NULL}; | |
char *cat[] = {"cat", NULL}; | |
char *wc[] = {"wc", "-c", NULL}; | |
char *head[] = {"head", "-c", "1000", NULL}; | |
char *time[] = {"time", "-p", "sleep", "3", NULL}; | |
char *echo[] = {"echo", "toto", NULL}; | |
char **cmd[] = {cat, ls, cat, NULL}; | |
pipeline(cmd); | |
return (0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I used https://gist.github.com/iomonad/a66f6e9cfb935dc12c0244c1e48db5c8 as reference.
As mentioned there, even though it is very useful to understand, some problem remains.
So, I tried to resolve the problem.
Thanks.