Основная проблема
Ваша ключевая проблема заключается в том, что вы звоните pipe()
после того, как вы позвонили fork()
. Это означает, что два процесса имеют совершенно разные каналы; они не разговаривают друг с другом.
Вторичные проблемы
Конечно, есть и другие проблемы.
У вас есть (в родителе) : int c=write(fd[1],h,sizeof(h));
. Вы пишете 8 байтов (ваш вывод включает C: 8
, потому что переменная h
является указателем размера 8
(вы в 64-битной системе). Однако строка указывает только на 4 байта - вы следует использовать strlen()
или около того, чтобы ограничить объем записываемых данных.
Вы не закрываете достаточно файловых дескрипторов для удобства.
У вас есть аргументы для dup2()
в обратном порядке. Это тоже крайне важно.
Кажется странным использовать динамическое распределение c только для 4 байтов данных, но это должно работать .
Вы должны напечатать PID вместе со значением в hello
в дочернем (для согласованности, если ничего больше). Хорошо, что вы делаете это с другой печатью.
Вероятно, родитель должен ждать ребенка после l oop (после закрытия трубы).
Функция sleep()
принимает целое число; вызов sleep(0.1)
спит в течение нуля секунд. Для сна менее секунды вам нужно nanosleep()
или может быть. usleep()
(более старый, больше не является частью POSIX, но широко доступен и прост в использовании).
Вот рабочий код:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
volatile sig_atomic_t sigchld = 0;
static void sigchldHandler(int signum)
{
sigchld = signum;
}
int main(void)
{
sigset_t mask, prev;
signal(SIGCHLD, sigchldHandler);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
int fd[2];
pipe(fd);
int pid = fork();
sigprocmask(SIG_BLOCK, &mask, &prev);
if (pid == 0)
{
/* Child */
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
printf("(%d) Child here stopping self\n", getpid());
raise(SIGSTOP);
printf("(%d) CONTINUING\n", getpid());
char *hello = malloc(sizeof("hi\n"));
int nbytes = read(STDIN_FILENO, hello, sizeof("hi\n"));
printf("(%d) received %d bytes: %.*s\n", getpid(), nbytes, nbytes, hello);
exit(0);
}
/* Parent */
close(fd[0]);
nanosleep(&(struct timespec){.tv_sec = 0, .tv_nsec = 100000000}, NULL);
sigprocmask(SIG_SETMASK, &prev, NULL);
while (1)
{
if (sigchld)
{
int status;
int p = waitpid(-1, &status, WNOHANG | WUNTRACED);
if (WIFSTOPPED(status))
{
if (WSTOPSIG(status) == SIGSTOP)
{
printf("(%d) SAYS: %d\n", p, WSTOPSIG(status));
kill(pid, SIGCONT);
char *h = "hi\n";
int c = write(fd[1], h, strlen(h));
printf("DATA WRITTEN: %i\n", c);
close(fd[1]);
break;
}
}
sigchld = 0;
}
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("PID %d exited with status 0x%.4X\n", corpse, status);
return 0;
}
Пример вывода:
(66589) Child here stopping self
(66589) SAYS: 17
DATA WRITTEN: 3
(66589) CONTINUING
(66589) received 3 bytes: hi
PID 66589 exited with status 0x0000
Разница между 17 (на Ma c под управлением macOS Mojave 10.14.6) и 19 (на Linux коробке) является нормальной; POSIX не стандартизирует фактические значения номеров сигналов (хотя сигналы от 1 SIGHUP
до 15 SIGTERM
одинаковы для всех систем, поскольку они были стандартными в 7-м издании Unix).