Witam,
Zastanawiałem się jak działa tworzenie potoku w bashu, np:
sleep 3600 | cat | sort -u | cut -d' ' -f1
Tutaj oczywiście nic się nie przenosi na kolejne programy (sleep nic nie wypisuje, tylko czeka), ale mi będzie chodziło o zasadę tworzenia takiego potoku w C. Używając polecenia ps razem z tym wyżej dostaję taki wynik:
sleep 3600 | cat | sort -u | cut -d' ' -f1 & ps -Hp $$ --ppid $$ -o pid,pgid,ppid,sid,tname,comm
PID PGID PPID SID TTY COMMAND
67855 67855 5971 67855 pts/0 bash
73274 73274 67855 67855 pts/0 sleep
73275 73274 67855 67855 pts/0 cat
73276 73274 67855 67855 pts/0 sort
73277 73274 67855 67855 pts/0 cut
73278 73278 67855 67855 pts/0 ps
Otwarte deskryptory plików dla każdego programu:
for PID in `ps --ppid $$ -o pid=` ; do cat /proc/$PID/comm 2>/dev/null ; ls -l /proc/$PID/fd 2>/dev/null ; echo ; done
sleep
razem 0
lrwx------ 1 admin admin 64 10-18 22:23 0 -> /dev/pts/0
l-wx------ 1 admin admin 64 10-18 22:23 1 -> 'pipe:[38322102]'
lrwx------ 1 admin admin 64 10-18 22:23 2 -> /dev/pts/0
cat
razem 0
lr-x------ 1 admin admin 64 10-18 22:23 0 -> 'pipe:[38322102]'
l-wx------ 1 admin admin 64 10-18 22:23 1 -> 'pipe:[38322104]'
lrwx------ 1 admin admin 64 10-18 22:23 2 -> /dev/pts/0
sort
razem 0
lr-x------ 1 admin admin 64 10-18 22:23 0 -> 'pipe:[38322104]'
l-wx------ 1 admin admin 64 10-18 22:23 1 -> 'pipe:[38322105]'
lrwx------ 1 admin admin 64 10-18 22:23 2 -> /dev/pts/0
cut
razem 0
lr-x------ 1 admin admin 64 10-18 22:23 0 -> 'pipe:[38322105]'
lrwx------ 1 admin admin 64 10-18 22:23 1 -> /dev/pts/0
lrwx------ 1 admin admin 64 10-18 22:23 2 -> /dev/pts/0
Analizując to stwierdziłem, że bash tworzy pipe dla każdego wystąpienia znaku "|", ponadto ustawia PGID dla każdego następnego procesu na PID pierwszego procesu w potoku. Tak więc, czy takie coś w C odzwierciedla to, co bash robi? Czy może czegoś nie zauważyłem, co jeszcze bash robi w przypadku potoków?
const char * const (* const cmd[])[] = {
&(const char * const[]){"sleep", "3600", NULL},
&(const char * const[]){"cat", NULL},
&(const char * const[]){"sort", "-u", NULL},
&(const char * const[]){"cut", "-d ", "-f1", NULL},
NULL
};
struct {
int next_read;
int write;
int read;
} pipes;
int pid, pgid = 0, index = 0;
while (cmd[index] != NULL) {
if (cmd[index + 1] != NULL)
pipe((int*)&pipes);
if (!(pid = fork())) {
setpgid(0, pgid);
if (index > 0) {
dup2(pipes.read, 0);
close(pipes.read);
}
if (cmd[index + 1] != NULL) {
close(pipes.next_read);
dup2(pipes.write, 1);
close(pipes.write);
}
execvp((*cmd[index])[0], (char * const *)cmd[index]);
}
if (index > 0)
close(pipes.read);
else
pgid = pid;
if (cmd[index + 1] != NULL) {
pipes.read = pipes.next_read;
close(pipes.write);
}
++index;
}