Pipe Programming

āđāļāļāđ (Pipe)
āļŦāļĨāļēāļĒāđāļāļĢāļąāđāļāļāļĩāđāļāļđāđāđāļāđāļāļēāļāļĢāļ°āļāļāļāļāļīāļāļąāļāļīāļāļēāļĢāļĨāļĩāļāļļāļāļāđāļāļ°āļāđāļāļāļĄāļĩāļāļēāļĢāđāļāđāļāļģāļŠāļąāđāļāļĄāļēāļāļāļ§āđāļēāļŦāļāļķāđāļāļāļģāļŠāļąāđāļāđāļāļ·āđāļāļāđāļāļāļāļēāļĢāļāļĩāđāļāļ°āļāļĢāļāļāļāđāļāļĄāļđāļĨāļāļĩāđāļāđāļāļāļāļēāļĢ āđāļāļĒāđāļāļ·āđāļāļĄāļāļļāļāļāļģāļŠāļąāđāļāđāļŦāļĨāđāļēāļāļąāđāļāļāđāļ§āļĒāđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒ â|
â āļŦāļĢāļ·āļāđāļĢāļĩāļĒāļāļ§āđāļēāđāļāļāđ (Pipe) āļāļąāļāļāļąāļ§āļāļĒāđāļēāļāļāđāļēāļāļĨāđāļēāļ āļāļķāđāļāļāļĨāļĨāļąāļāļāđāļāļāļāļāļģāļŠāļąāđāļāļāđāļēāļāļāđāļēāļĒāļāļ°āļŠāđāļāđāļāđāļēāđāļāđāļāļāļīāļāļāļļāļāļāđāļāđāļāļāļāļāļāļģāļŠāļąāđāļāļāđāļēāļāļāļ§āļēāļāļĒāđāļēāļāļāļĩāđāđāļāđāļĢāļ·āđāļāļĒāđāļāļāļāļĢāļ°āļāļąāđāļāļāļķāļāļāļģāļŠāļąāđāļāļŠāļļāļāļāđāļēāļĒāļāļĨāļĨāļąāļāļāđāļāđāļāļ°āđāļŠāļāļāļāļāļāļŦāļāđāļēāļāļāđāļāļāļĩāđāļŠāļļāļ
$ echo "Hello World" | awk '{print $1}'
Hello
āļāđāļ (Pipe) āđāļāđāļāļāļĢāļ°āļāļ§āļāļāļēāļĢāļāļĩāđāđāļāđāđāļāļāļēāļĢāļāļīāļāļāđāļāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāļāļĩāđāļāđāļēāļĒāļāļĩāđāļŠāļļāļāļāļ·āļāļāļēāļĢāļāļģāļāļĨāļĨāļąāļāļāđāļāļĩāđāđāļāđāļāļēāļāđāļāļĢāđāļāļĢāļĄāļŦāļāļķāđāļāđāļāđāļāđāļāļāļīāļāļāļļāļāļāļāļāļāļĩāļāđāļāļĢāđāļāļĢāļĄāļŦāļāļķāđāļ āđāļāļĒāđāļāļāđāļāļ°āđāļāđāļāļāļąāļ§āļāļĨāļēāļāđāļāļāļēāļĢāļŠāđāļāļāđāļāļĄāļđāļĨāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāļāļķāđāļāļāļēāļĢāļŠāđāļāļāđāļāļĄāļđāļĨāļāļ°āđāļāđāļāđāļāļāļāļīāļĻāļāļēāļāđāļāļĩāļĒāļ§ (unidirectional) āļāļąāļāļĢāļđāļ

āđāļāļĒāđāļĄāļ·āđāļāđāļāļĢāđāļāļŠāļŦāļāļķāđāļāļāđāļāļāļāļēāļĢāļŠāļĢāđāļēāļāđāļāļāđāļāļķāđāļāļĄāļē āļāļāļ§āļāļāļēāļĢāļāļāļāđāļāļāļĢāđāđāļāļĨāļāđāļāļ°āļāļģāļāļēāļĢāļŠāļĢāđāļēāļ file descriptor (fd)
āļāļķāđāļāļĄāļēāļŠāļāļāđāļāļĨāđāļŠāļģāļŦāļĢāļąāļāđāļāđāđāļāļāļēāļĢāļŠāļĢāđāļēāļ pipe āļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāđāļĨāļ°āđāļāļāļĢāđāđāļāļĨ āđāļāļĒāđāļāļĨāđ fd āļāļąāļ§āđāļĢāļāļāļ°āļāļđāļāđāļāđāđāļāđāļāđāļŠāđāļāļāļēāļāļāļēāļĢāļāđāļāļāļāđāļāļĄāļđāļĨāļŦāļĢāļ·āļāđāļāļĩāļĒāļāļāđāļāļĄāļđāļĨāđāļāđāļēāđāļāđāļ pipe (write) āļŠāđāļ§āļāđāļāļĨāđ fd āļāļąāļ§āļāļĩāđāļŠāļāļāļāļ°āđāļāđāđāļāđāļāļāļąāļ§āļĢāļąāļāļāđāļāļĄāļđāļĨāļāļĩāđāđāļāđāļĄāļēāļāļēāļ pipe (read) āļāļģāđāļŦāđāđāļāļĢāđāļāļŠāļāļąāđāļāļŠāļēāļĄāļēāļĢāļāđāļāđ pipe āđāļāļāļēāļĢāļŠāđāļāļāđāļāļĄāļđāļĨāđāļāļĄāļēāđāļŦāđāļāļąāļāđāļāļāļ āļēāļĒāđāļāđāļāļĢāđāļāļŠāđāļāđ āļāļąāļāđāļŠāļāļāđāļāļĢāļđāļāļāđāļēāļāļĨāđāļēāļ

āļāļēāļāļĢāļđāļāļāđāļēāļāļāđāļāđāļŠāļāļāđāļŦāđāđāļŦāđāļāļ§āđāļēāđāļĄāļ·āđāļāđāļāļĨāđ fd āļāļąāđāļāļŠāļāļ (pfd0
āđāļĨāļ° pfd1
) āļāļđāļāđāļāļ·āđāļāļĄāļāļķāļāļāļąāļāđāļĨāđāļ§ āđāļĄāļ·āđāļāđāļāļĢāđāļāļŠāļāđāļāļāļāļēāļĢāļāļĩāđāļāļ°āļŠāđāļāļāđāļāļĄāļđāļĨāļāđāļēāļ pipe (pfd1
) āļāđāļāļĄāļđāļĨāļāđāļāļ°āļāļđāļāļŠāđāļāļāđāļēāļāđāļāļāļĢāđāđāļāļĨāļāļĩāđāļŠāļĢāđāļēāļāđāļāđāļ pipe āļāļķāđāļāļĄāļēāđāļĨāđāļ§āļāđāļēāļāļāđāļāļĄāļđāļĨāļāļąāđāļāļāđāļāđāļāļĒāļąāļāļāļĩāļāļāđāļēāļāļāļāļ pipe āđāļāļ·āđāļāļāļĨāļēāļĒāđāļāđāļāļāļīāļāļāļļāļāļāļāļāđāļāļĢāđāļāļŠāļĄāļēāļĒāļąāļāđāļāļĨāđ pfd0
āļāļąāļāđāļŠāļāļāđāļāļĢāļđāļāļāđāļēāļāļĨāđāļēāļ

āđāļāļāļēāļĢāđāļāđāļāļēāļāļāļĢāļīāļāļāļąāđāļ pipe āļāļ°āļāļģāļĄāļēāđāļāđāļĄāļēāļāđāļāļāļēāļĢāļŠāļ·āđāļāļŠāļēāļĢāļāđāļāļĄāļđāļĨāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāđāļĄāđāđāļĨāļ°āđāļāļĢāđāļāļŠāļĨāļđāļ āđāļāļ·āđāļāļāļāļēāļāđāļāļĢāđāļāļŠāļāļ°āđāļāđāļĢāļąāļāļŠāļ·āļāļāļāļ (inherit) āđāļāļāļĢāļąāļāļĒāļēāļāļĢāļāđāļēāļāđāļāļēāļāđāļāļĢāđāļāļŠāđāļĄāđ āđāļāđāļ file descriptors āļāļąāđāļāļŦāļĨāļēāļĒāļāļĩāđāđāļāļĢāđāļāļŠāđāļĄāđāđāļāđāļŠāļĢāđāļēāļāđāļāļēāđāļ§āđāļāļąāļāļāļĩ āļāļąāļāđāļŠāļāļāđāļāļĢāļđāļāļāđāļēāļāļĨāđāļēāļ

āļāļēāļāļĢāļđāļāļāđāļēāļāļāđāļāļāļ°āļŠāļąāļāđāļāļāđāļŦāđāļāļ§āđāļēāļāļąāđāļāļŠāļāļāđāļāļĢāđāļāļŠāļĄāļĩāļāļēāļĢāđāļāđāļēāđāļāđāļāļēāļāđāļāļĨāđ pfd0 āđāļĨāļ° pfd1 āļāļąāļāļāļąāđāļāđāļāļ·āđāļāđāļŦāđāļāļēāļĢāļŠāļ·āđāļāļŠāļēāļĢāļĢāļ°āļŦāļ§āđāļēāļāļāļąāđāļāļŠāļāļāļāļĒāļđāđāđāļāļāļāđāļāļāļāđāļāļāļ pipe āļāļ·āļāđāļāļāļāļīāļĻāļāļēāļāđāļāļĩāļĒāļ§ (unidirectional) āļāļ°āļāđāļāļāļāļģāļŦāļāļāļ§āđāļēāđāļāļĢāđāļāļŠāđāļāđāļāđāļāļāļāļŠāđāļāđāļĨāļ°āđāļāļĢāđāļāļŠāđāļāđāļāđāļāļāļāļĢāļąāļ āļāļąāļāļāļąāļ§āļāļĒāđāļēāļāļāđāļēāļāļĨāđāļēāļāđāļŠāļāļāđāļŦāđāđāļŦāđāļāļāļķāļāļāļąāļ§āđāļāļĢāđāļāļŠāļĨāļđāļāļāļ°āļāļģāļŦāļāđāļēāļāļĩāđāļŠāđāļāļāđāļāļĄāļđāļĨ (write) āļāđāļēāļ pipe āđāļāļĒāļąāļāđāļāļĢ-āđāļāļŠāđāļĄāđ (read)

āđāļāđāļāļĒāđāļēāļāđāļĢāļāđāļāļēāļĄāļāđāļŠāļēāļĄāļēāļĢāļāļŠāļĢāđāļēāļāļāļēāļĢāļŠāļ·āđāļāļŠāļēāļĢāļāđāļāļĄāļđāļĨāđāļāļāļĒāļđāđāđāļāđāļāļāļŠāļāļāļāļīāļĻāļāļēāļāđāļāđ (bi-directional) āđāļāļĒāļāļēāļĢāđāļāļīāđāļĄ pipe āļāļķāđāļāļĄāļēāļāļĩāļāļāđāļ āđāļāļĒāļāļģāļŦāļāļāđāļŦāđāđāļāļĢāđāļāļŠāđāļĄāđāđāļāđāļāļāļāļŠāđāļāļāđāļāļĄāļđāļĨ (write) āđāļāļĒāļąāļāđāļāļĢāđāļāļŠāļĨāļđāļ (read) āđāļāđāđāļāđāļāļāļąāļ āļāļķāđāļ system call āļāļĩāđāđāļāđāđāļāļāļēāļĢāđāļāļĩāļĒāļāđāļĨāļ°āļāđāļēāļāļāđāļāļĄāļđāļĨāļāđāđāļāđāļāļ·āđāļāļāļąāļāļāđāļāļąāļāļ§āđāļē write()
āđāļĨāļ° read()
āļāļĢāļāđāđāļāđāļāļąāļāļāļĩ āļĒāļāđāļ§āđāļāđāļĄāđāļŠāļēāļĄāļēāļĢāļāđāļāđāļāļąāļāļāđāļāļąāļ lseek()
āđāļāđāļāļąāļ file descriptor āļāļāļ pipe āđāļāđ āļāļąāļāļāļąāđāļāļāđāļēāļāđāļāļāļāļēāļĢāđāļāđāđāļāļĢāđāļāļŠāļŠāļēāļĄāļēāļĢāļāļŠāļ·āđāļāļŠāļēāļĢāļāļąāļāđāļāđāļāļąāđāļāļŠāļāļāļāļīāļĻāļāļēāļ (bi-directional) āļāļ°āļāđāļāļāđāļāđ pipe āļāļģāļāļ§āļ n*(n-1)
āđāļāļĒāļāļĩāđ n āļāļ·āļāļāļģāļāļ§āļāđāļāļĢāđāļāļŠ
āļāļēāļĢāļāļąāļāļāļēāđāļāļĢāđāļāļĢāļĄāļŠāļ·āđāļāļŠāļēāļĢāļāđāļ§āļĒāļ§āļīāļāļĩāļāļēāļĢāļŠāļāļĢāļĩāļĄāļāđāļāļĄāļđāļĨāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāļāļāļīāļāļāļēāļāđāļāļĩāļĒāļ§āļāļĩāđāļāļ°āđāļāđāļāļąāļāļāđāļāļąāļ pipe āļāļĩāđāļāļĒāļđāđāļ āļēāļĒāđāļāđāļāļĨāđāđāļĨāļāļĢāļēāļĢāļĩāļāļ·āđāļāļ§āđāļē unistd.h
#include <unistd.h>
int pipe ( int pfd[2] ); <--- pfd āļāļąāļ§āđāļāļĢ array āļŠāļģāļŦāļĢāļąāļāđāļāđāļāļāđāļē file descriptors
pfd[0] - file descriptor āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļāđāļēāļ
pfd[1] - file descriptor āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāđāļāļĩāļĒāļ
āļŠāļāļēāļāļ°āļāļēāļĢāļāļģāļāļēāļāļāļāļ pipe
0 - āļāļģāđāļāļīāļāļāļēāļĢāđāļāđāļŠāļģāđāļĢāđāļ
-1 - āļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāļĨāđāļĄāđāļŦāļĨāļ§
āļāļēāļāļĢāļđāļāļāđāļēāļāļāļāđāļŠāļāļāļāļēāļĢāļāļģāļāļēāļāļāļāļāļāļąāļāļāđāļāļąāļ pipe āļāļķāđāļāļāļ°āļŠāļĢāđāļēāļāļāđāļāļāļāļēāļāļŠāļ·āđāļāļŠāļēāļĢāļāļāļīāļāļāļēāļāđāļāļĩāļĒāļ§āļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāđāļāļĒāļāļ°āļāļ·āļāļāđāļē file descriptor āļāļąāđāļāļŠāļāļāļāļąāđāļ āļāđāļēāļāļāļąāļ§āđāļāļĢ pfd[]
āļāļĨāđāļēāļ§āļāļ·āļ āļāļĨāļēāļĒāļŦāļāļķāđāļāļŠāļģāļŦāļĢāļąāļāļāđāļēāļ (pfd[0]
) āđāļĨāļ°āļāļĩāļāļāļĨāļēāļĒāļŦāļāļķāđāļāļŠāļģāļŦāļĢāļąāļāđāļāļĩāļĒāļ (pfd[1]
) āļāđāļēāļāļāļ file descriptor āđāļāđāļāļāļāļīāļāļāļģāļāļ§āļāđāļāđāļĄ (int
) āļāļĩāđāļĢāļ°āļāļāļāļāļīāļāļąāļāļīāļāļēāļĢāļĨāļĩāļāļļāļāļāđāļāļ°āđāļāđāđāļāļāļēāļĢāļāđāļēāļāļāļīāļāļāļķāļāđāļāđāļĄāļāļĩāđāļĄāļĩāļāļēāļĢāđāļāļīāļāđāļāđāļāļēāļāļāļąāļāļāļąāđāļāđāļĄāļ·āđāļāđāļĢāļĩāļĒāļāđāļāđāļāļēāļāļāļąāļāļāđāļāļąāļ pipe āļāļ°āļāđāļāļāļŠāđāļāļāļēāđāļĢāļĒāđāļāļāļāļāļģāļāļ§āļāđāļāđāļĄāļāļĩāđāļĄāļĩāļŠāļĄāļēāļāļīāļ 2 āļāļąāļ§āđāļŦāđāđāļāđ āļāļąāļāļāđāļāļąāļ pipe()
int pfd[2]; // file descriptor āļāļāļ pipe
āđāļŠāļāļāļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢāļŠāļĢāđāļēāļ pipe āđāļāļĒāđāļāđāļāļģāļŠāļąāđāļ pipe()
āđāļāļ·āđāļāđāļāđāļāļāđāļāđāļāļ·āđāļāļĄāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāđāļĄāđāđāļĨāļ°āđāļāļĢāđāļāļŠāļĨāļđāļ āđāļāļĒāļāļĩāđāđāļāļĢāđāļāļŠāļĨāļđāļāļāļ°āļāļģāļāļēāļĢāļŠāđāļāļāđāļāļĄāļđāļĨāđāļāļĒāļąāļāđāļāļĢāđāļāļŠāđāļĄāđ āđāļāļĒāļāļēāļĢāđāļāļĩāļĒāļāļĨāļ pfd[1]
āļāļąāļāļĢāļđāļāļāđāļēāļāļĨāđāļēāļ

// pipe1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
pid_t pid;
int pfd[2];
int ret;
char buf[20];
ret = pipe(pfd);
if (ret == -1) {
perror("pipe");
exit(1);
}
pid = fork();
if (pid == 0) {
/* Child Process */
printf("Child Process\n");
write(pfd[1], "Hello there!", 12);
} else {
/* Parent Process */
printf("Parent Process\n");
read(pfd[0], buf, 15);
printf("buf : %s\n", buf);
}
return 0;
}
āļāļāļĄāđāļāļĨāđāđāļāļĢāđāļāļĢāļĄ pipe.c
āđāļĨāļ°āļāļāļŠāļāļāļāļēāļĢāļŠāđāļāļāđāļāļĄāļđāļĨāļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāļāļąāđāļāļŠāļāļ (āđāļāļĢāđāļāļŠ parent āđāļĨāļ°āđāļāļĢāđāļāļŠ child)
$ gcc -o pipe1 pipe1.c
$ ./pipe1
Parent Process
Child Process
buf : Hello there!
āđāļŠāļāļāļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢāļŠāļĢāđāļēāļ pipe āļŠāļģāļŦāļĢāļąāļāļāļļāļāļāļģāļŠāļąāđāļ sort
āļāļĩāđāļāļ°āļĢāļąāļāļāđāļāļĄāļđāļĨ (write) āļāļēāļāļāđāļēāđāļāđāļāļąāļ§āđāļāļĢāļāļēāđāļĢāļĒāđ āđāļāļ·āđāļāļāļģāļāļēāļĢāļāļąāļāđāļĢāļĩāļĒāļāļāđāļāļĄāļđāļĨ
/*****************************************************************************
Excerpt from "Linux Programmer's Guide - Chapter 6"
(C)opyright 1994-1995, Scott Burkett
*****************************************************************************
Filename: pipe2.c
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRS 5
int main(void) {
int cntr;
FILE *pipe_fp;
char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", "delta" };
/* Create one way pipe line with call to popen() */
if ((pipe_fp = popen("sort", "w")) == NULL) {
perror("popen");
exit(1);
}
/* Processing loop */
for (cntr = 0; cntr < MAXSTRS; cntr++) {
fputs(strings[cntr], pipe_fp);
fputc('\n', pipe_fp);
}
/* Close the pipe */
pclose(pipe_fp);
return (0);
}
$ gcc -o pipe2 pipe2.c -Wall
$ ./pipe2
alpha
bravo
charlie
delta
echo
āđāļāļ·āđāļāļāļāļēāļāļāļąāļāļāđāļāļąāļ popen()
āļāļ°āđāļāđ shell āđāļāļāļēāļĢāļĢāļąāļāļāļģāļŠāļąāđāļāļāļĩāđāļĢāļ°āļāļļāđāļāđāļŦāđ āļāļąāļāļāļąāđāļāļāļēāļĢāđāļāđāļāļļāļāļāļģāļŠāļąāđāļāļāđāļŠāļēāļĄāļēāļĢāļāļāļģāđāļāđāđāļŦāļĄāļ·āļāļāļāļąāļāļāļēāļĢāļāļīāļĄāļāđāļāļģāļŠāļąāđāļāļāļ shell (command line) āđāļāđāđāļāđāļāļāļąāļ āļāļąāļ§āļāļĒāđāļēāļāđāļāđāļ
popen("ls /usr/include", "r");
popen("sort > /tmp/foo", "w");
popen("sort | uniq | more", "w");
āđāļŠāļāļāļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢāđāļāđ popen()
āđāļāļ·āđāļāļĢāļąāļāļāđāļāļĄāļđāļĨāļāļĩāđāļāđāļēāļāđāļāđāļāļēāļāļāļģāļŠāļąāđāļ ls āđāļĨāđāļ§āļŠāđāļāļāđāļāđāļāđāļāđāļāļāļīāļāļāļļāļāđāļŦāđāļāļąāļāļāļĩāļāļāļģāļŠāļąāđāļ (sort) āđāļāļ·āđāļāļāļģāļāļēāļĢāļāļąāļāđāļĢāļĩāļĒāļāļāđāļāļĄāļđāļĨāļāđāļāđāļ
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *pipein_fp, *pipeout_fp;
char readbuf[80];
/* Create one way pipe line with call to popen() */
if ((pipein_fp = popen("ls /", "r")) == NULL) {
perror("popen");
exit(1);
}
/* Create one way pipe line with call to popen() */
if ((pipeout_fp = popen("sort", "w")) == NULL) {
perror("popen");
exit(1);
}
/* Processing loop */
while (fgets(readbuf, 80, pipein_fp))
fputs(readbuf, pipeout_fp);
/* Close the pipes */
pclose(pipein_fp);
pclose(pipeout_fp);
return (0);
}
$ ls /
NAS courseweb_backup etc initrd.img.old lib64 mnt root selinux tftpboot var bin dev home lib lost+found opt run srv tmp vmlinuz boot ee_backup initrd.img lib32 media proc sbin sys usr vmlinuz.old
$ gcc -o pipe3 pipe3.c -Wall
$ ./pipe3
NAS
bin
boot
courseweb_backup
dev
ee_backup
etc
home
initrd.img
initrd.img.old
lib
lib32
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
selinux
srv
sys
tftpboot
tmp
usr
var
vmlinuz
vmlinuz.old
āđāļŠāļāļāļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢāļĢāļąāļāļāļēāļĢāđāļāļīāļ§āđāļĄāļāļāđāļāļēāļāļāļđāđāđāļāđāļāđāļēāļāļāļēāļĢāđāļĢāļĩāļĒāļāđāļāļĢāđāļāļĢāļĄāļāļēāļ command line āđāļāļĒāļāļēāļĢāđāļāļīāļ§āđāļĄāļāļāđāļāļąāļ§āđāļĢāļāļāļ°āđāļāđāļāļāļģāļŠāļąāđāļāļāļĩāđāļāđāļāļāļāļēāļĢāđāļŦāđāļĢāļąāļāļāđāļāļĄāļđāļĨ (write
) āđāļĨāļ°āļāļēāļĢāđāļāļīāļ§āđāļĄāļāļāđāļāļĩāđāļŠāļāļāļāļ°āđāļāđāļāđāļāļĨāđāļāđāļāļĄāļđāļĨāļāļĩāđāļāđāļāļāļāļēāļĢāļāļ°āđāļŦāđāđāļāļīāļāļāđāļēāļ (rt
)
/*****************************************************************************
Excerpt from "Linux Programmer's Guide - Chapter 6"
(C)opyright 1994-1995, Scott Burkett
*****************************************************************************
Filename: popen.c
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *pipe_fp, *infile;
char readbuf[80];
if (argc != 3) {
fprintf(stderr, "USAGE: popen3 [command] [filename]\n");
exit(1);
}
/* Open up input file */
if ((infile = fopen(argv[2], "rt")) == NULL) {
perror("fopen");
exit(1);
}
/* Create one way pipe line with call to popen() */
if ((pipe_fp = popen(argv[1], "w")) == NULL) {
perror("popen");
exit(1);
}
/* Processing loop */
do {
fgets(readbuf, 80, infile);
if (feof(infile))
break;
fputs(readbuf, pipe_fp);
} while (!feof(infile));
fclose(infile);
pclose(pipe_fp);
return (0);
}
$ gcc -o popen popen.c -Wall
$ ./popen sort popen.c
$ ./popen cat popen.c
$ ./popen more popen.c
$ ./popen cat popen.c | grep main
āđāļŠāļāļāļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢāļāļĢāļ°āļĒāļļāļāļāđāļāļēāļĢāļŠāđāļāļāđāļāļāļ§āļēāļĄ (message) āļĢāļ°āļŦāļ§āđāļēāļāđāļāļĢāđāļāļŠāļāđāļēāļāđ āđāļāļĒāđāļāļĢāđāļāļŠāļāļĩāđ i
āļāđāļāļāļāļēāļĢāļŠāđāļāđāļāļĒāļąāļāđāļāļĢāđāļāļŠāļāļĩāđ j
āđāļāļĒāļāđāļēāđāļāļĢāđāļāļŠāđāļāļĢāļąāļāļāđāļāļāļ§āļēāļĄāđāļāļĩāļĒāļāļŠāļāļāļāļĢāļąāđāļāđāļĨāđāļ§āļāđāļāļ°āļŠāļīāđāļāļŠāļļāļāļāļēāļĢāļāļģāļāļēāļ
/*
* pipe4.c
*
* A set of processes randomly messaging each the other, with pipes.
*
*
* Created by Mij <[email protected]> on 05/01/05.
* Original source file available on http://mij.oltrelinux.com/devel/unixprg/
*
*/
#include <stdio.h>
/* for read() and write() */
#include <sys/types.h>
#include <sys/uio.h>
/* for strlen and others */
#include <string.h>
/* for pipe() */
#include <unistd.h>
/* for [s]random() */
#include <stdlib.h>
/* for time() [seeding srandom()] */
#include <time.h>
/* for signals */
#include <signal.h>
#define PROCS_NUM 15 /* 1 < number of processes involved <= 255 */
#define MAX_PAYLOAD_LENGTH 50 /* message length */
#define DEAD_PROC -1 /* a value to mark a dead process' file descriptors with */
/* *** DATA TYPES *** */
/* a process address */
typedef char proc_addr;
/* a message */
struct message_s {
proc_addr src_id;
short int length;
char *payload;
};
/* *** FUNCTION PROTOTYPES *** */
/* send message to process with id dest */
int send_proc_message(proc_addr dest, char *message);
/* receive a message in the process' queue of received ones */
int receive_proc_message(struct message_s *msg);
/* mark process file descriptors closed */
void mark_proc_closed(proc_addr process);
/* *** GLOBAL VARS *** */
/* they are OK to be global here. */
proc_addr my_address; /* stores the id of the process */
int proc_pipes[PROCS_NUM][2]; /* stores the pipes of every process involved */
int main(int argc, char *argv[]) {
pid_t child_pid;
pid_t my_children[PROCS_NUM]; /* PIDs of the children */
int i, ret;
char msg_text[MAX_PAYLOAD_LENGTH]; /* payload of the message to send */
proc_addr msg_recipient;
struct message_s msg;
/* create a pipe for me (the parent) */
pipe(proc_pipes[0]);
/* initializing proc_pipes struct */
for (i = 1; i < PROCS_NUM; i++) {
/* creating one pipe for every (future) process */
ret = pipe(proc_pipes[i]);
if (ret) {
perror("Error creating pipe");
abort();
}
}
/* fork [1..NUM_PROCS] children. 0 is me. */
for (i = 1; i < PROCS_NUM; i++) {
/* setting the child address */
my_address = my_address + 1;
child_pid = fork();
if (!child_pid) {
/* child */
sleep(1);
/* closing other process' pipes read ends */
for (i = 0; i < PROCS_NUM; i++) {
if (i != my_address)
close(proc_pipes[i][0]);
}
/* init random num generator */
srandom(time(NULL));
/* my_address is now my address, and will hereby become a "constant" */
/* producing some message for the other processes */
while (random() % (2 * PROCS_NUM)) {
/* interleaving... */
sleep((unsigned int) (random() % 2));
/* choosing a random recipient (including me) */
msg_recipient = (proc_addr) (random() % PROCS_NUM);
/* preparing and sending the message */
sprintf(msg_text, "hello from process %u.", (int) my_address);
ret = send_proc_message(msg_recipient, msg_text);
if (ret > 0) {
/* message has been correctly sent */
printf(" --> %d: sent message to %u\n", my_address,
msg_recipient);
} else {
/* the child we tried to message does no longer exist */
mark_proc_closed(msg_recipient);
printf(" --> %d: recipient %u is no longer available\n",
my_address, msg_recipient);
}
}
/* now, reading the first 2 messages we've been sent */
for (i = 0; i < 2; i++) {
ret = receive_proc_message(&msg);
if (ret < 0)
break;
printf(
"<-- Process %d, received message from %u: \"%s\".\n",
my_address, msg.src_id, msg.payload);
};
/* i'm exiting. making my pipe widowed */
close(proc_pipes[my_address][0]);
printf("# %d: i am exiting.\n", my_address);
exit(0);
}
/* saving the child pid (for future killing) */
my_children[my_address] = child_pid;
/* parent. I don't need the read descriptor of the pipe */
close(proc_pipes[my_address][0]);
/* this is for making srandom() consistent */
sleep(1);
}
/* expecting the user request to terminate... */
printf("Please press ENTER when you like me to flush the children...\n");
getchar();
printf("Ok, terminating dandling processes...\n");
/* stopping freezed children */
for (i = 1; i < PROCS_NUM; i++) {
kill(my_children[i], SIGTERM);
}
printf("Done. Exiting.\n");
return 0;
}
int send_proc_message(proc_addr dest, char *message) {
int ret;
char *msg = (char*) malloc(sizeof(message) + 2);
/* the write should be atomic. Doing our best */
msg[0] = (char) dest;
memcpy((void*) &(msg[1]), (void*) message, strlen(message) + 1);
/* send message, including the "header" the trailing '\0' */
ret = write(proc_pipes[dest][1], msg, strlen(msg) + 2);
free(msg);
return ret;
}
int receive_proc_message(struct message_s *msg) {
char c = 'x';
char temp_string[MAX_PAYLOAD_LENGTH];
int ret, i = 0;
/* first, getting the message sender */
ret = read(proc_pipes[my_address][0], &c, 1);
if (ret == 0) {
return 0;
}
msg->src_id = (proc_addr) c;
do {
ret = read(proc_pipes[my_address][0], &c, 1);
temp_string[i++] = c;
} while ((ret > 0) && (c != '\0') && (i < MAX_PAYLOAD_LENGTH));
if (c == '\0') {
/* msg correctly received. Preparing message packet */
msg->payload = (char*) malloc(strlen(temp_string) + 1);
strncpy(msg->payload, temp_string, strlen(temp_string) + 1);
return 0;
}
return -1;
}
void mark_proc_closed(proc_addr process) {
proc_pipes[process][0] = DEAD_PROC;
proc_pipes[process][1] = DEAD_PROC;
}
$ gcc --ansi --pedantic -o pipe4 pipe4.c
$ ./pipe4
--> 1: sent message to 3
--> 1: sent message to 8
--> 2: sent message to 0
--> 1: sent message to 5
--> 2: sent message to 4
--> 1: sent message to 10
--> 2: sent message to 9
--> 2: sent message to 0
--> 3: sent message to 11
--> 2: sent message to 6
--> 1: sent message to 2
--> 2: sent message to 12
--> 3: sent message to 14
<-- Process 4, received message from 4: "hello from process 2.".
--> 3: sent message to 13
--> 1: sent message to 3
--> 1: sent message to 9
--> 1: sent message to 12
--> 1: sent message to 3
--> 2: sent message to 6
--> 3: sent message to 7
<-- Process 5, received message from 5: "hello from process 1.".
--> 2: sent message to 12
--> 2: sent message to 5
--> 1: sent message to 7
--> 1: sent message to 4
<-- Process 4, received message from 0: "hello from process 1.".
# 4: i am exiting.
--> 1: sent message to 12
--> 1: sent message to 2
<-- Process 5, received message from 0: "hello from process 2.".
# 5: i am exiting.
--> 2: sent message to 14
--> 2: sent message to 1
--> 2: sent message to 10
--> 1: sent message to 8
--> 1: sent message to 0
--> 1: sent message to 0
--> 6: sent message to 13
--> 6: sent message to 8
--> 6: sent message to 14
--> 8: sent message to 14
--> 6: sent message to 14
--> 8: sent message to 8
--> 8: sent message to 11
--> 9: sent message to 14
--> 10: sent message to 0
^C
Last updated
Was this helpful?