Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
1911 return FALSE;1912 }Строки 1906–1912 порождают процесс, на этот раз закрывая оба канала, если
fork()errno1914 if (pid == 0) { /* порожденный процесс */1915 if (close(1) == -1)1916 fatal(_("close of stdout in child failed (%s)"),1917 strerror(errno));1918 if (dup(ctop[1]) != 1)1919 fatal(_{"moving pipe to stdout in child failed (dup: %s)"), strerror(errno));1920 if (close(0) == -1)1921 fatal(_("close of stdin in child failed (%s)"),1922 strerror(errno));1923 if (dup(ptoc[0]) != 0)1924 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));1925 if (close(ptoc[0]) == -1 || close(ptoc[1]) == -11926 || close(ctop[0]) == -1 || close(ctop[1]) == -1)1927 fatal(_("close of pipe failed (%s)"), strerror(errno));1928 /* stderr HE дублируется в stdout потомка */1929 execl("/bin/sh", "sh", "-c", str, NULL);1930 _exit(errno == ENOENT ? 127 : 126);1931 }Строки 1914–1931 обрабатывают код потомка, с соответствующей проверкой ошибок и сообщениями на каждом шагу. Строка 1915 закрывает стандартный вывод. Строка 1918 копирует записываемый конец канала от потомка к родителю на 1. Строка 1920 закрывает стандартный ввод, а строка 1923 копирует читаемый конец канала от родителя к потомку на 0. Если это все работает, стандартные ввод и вывод теперь на месте и подключены к родителю.
Строки 1925–1926 закрывают все четыре первоначальные дескрипторы файлов каналов, поскольку они больше не нужны. Строка 1928 напоминает нам, что стандартная ошибка остается на месте. Это лучшее решение, поскольку пользователь увидит ошибки от сопроцесса. Программа
awk2>&1Наконец, строки 1929–1930 пытаются запустить для оболочки
execl()1934 /* родитель */1935 rp->pid = pid;1936 rp->iop = iop_alloc(ctop[0], str, NULL);1937 if (rp->iop == NULL) {1938 (void)close(ctop[0]);1939 (void)close(ctop[1]);1940 (void)close(ptoc[0]);1941 (void)close(ptoc[1]);1942 (void)kill(pid, SIGKILL); /* overkill? (pardon pun) */19431944 return FALSE;1945 }Первым шагом родителя является настройка входного конца от сопроцесса. Указатель
rpstruct redirectFILE*IOBUF*iopIOBUFgawkСтрока 1935 сохраняет значение ID процесса. Строка 1936 выделяет память для новой
IOBUFNULLIOBUFЕсли выделение памяти потерпело неудачу, строки 1937–1942 производят очистку, закрывая каналы и посылая сигнал «kill» порожденным процессам, чтобы заставить их завершить работу. (Функция
kill()kill()killpg()1946 rp->fp = fdopen(ptoc[1], "w");1947 if (rp->fp == NULL) {1948 iop_close(rp->iop);1949 rp->iop = NULL;1950 (void)close(ctop[0]);1951 (void)close(ctop[1]);1952 (void)close(ptoc[0]);1953 (void)close(ptoc[1]);1954 (void)kill(pid, SIGKILL); /* избыточно? (пардон, каламбур)*/19551956 return FALSE;1957 }Строки 1946–1957 аналогичны. Они устанавливают вывод родителя на потомка, сохраняя дескриптор файла для записывающего конца канала от родителя к потомку в
FILE*fdopen()С этого момента записываемый конец канала от родителя к потомку и читаемый конец канала от потомка к родителю хранятся в более крупных структурах:
FILE*IOBUF1960 os_close_on_exec(ctop[0], str, "pipe", "from");1961 os_close_on_exec(ptoc[1], str, "pipe", "from");19621963 (void)close(ptoc[0]);1964 (void)close(ctop[1]);