В этой программе я меняю идентификатор группы дочернего процесса.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void) {
int status;
char b[4];
pid_t pid, ch_pid;
switch(pid=fork()) {
case -1:
perror("Fork failed");
exit(1);
case 0:
printf("\nCHILD: This is child process!\n");
printf("CHILD: My PID is-- %d\n", getpid());
printf("CHILD: My parent PID -- %d\n", getppid());
printf("CHILD: My GID is -- %d\n", getpgid(getpid()));
printf("CHILD: My SID is -- %d\n", getsid(getpid()));
int k = setpgid(getpid(),getpid()); /*Modifies group id. Therefore, when user press
Cn+C, ChPr can't die*/
printf("BEFORE SETPGRP CHILD: My GID is -- %d\n", getpgid(getpid()));
printf("BEFORE SETPGRP CHILD: My SID is -- %d\n", getsid(getpid()));
//read(0,b,4);
//printf("b: %s\n",b);
pause();
exit(0);
default:
printf("PARENT: This is parent process!\n");
printf("PARENT: My PID -- %d\n", getpid());
printf("PARENT: My child PID %d\n",pid);
printf("PARENT: My parent PID %d\n",getppid());
printf("PARENT: My GID %d\n",getpgid(getpid()));
printf("PARENT: My SID %d\n",getsid(getpid()));
pause();
exit(0);
}
return 0;
}
Но когда я пытаюсь вызвать "чтение" (закомментированные строки), терминал bash не читает и не выводит данные. Однако родительский процесс читает успешно. Почему? Родительский и дочерний процессы имеют одинаковый идентификатор сеанса. Это значит, что они управляются с общего терминала. Я заметил, что если я изменю GID для дочернего процесса и нажму Cntrl + C, родительский процесс будет прерван, а дочерний процесс станет сиротой. Итак, если я раскомментирую «прочитанное» в своей программе и нажму Cntrl + C, это убьет оба процесса. Может быть, неудачный вызов чтения посылает сигнал в bash? Спасибо!
Хорошо. Почему терминал должен посылать сигнал ???
Терминал имеет настройку группа процессов переднего плана. Когда оболочка запускает команды, она выполняет задания переднего плана в группе процессов переднего плана терминала, но фоновые задания помещаются в свою собственную группу процессов. Только группе процессов переднего плана разрешено читать с терминала. Если фоновый процесс пытается прочитать, он приостанавливается; когда пользователь перемещает его на передний план, группа процессов терминала изменяется на эту группу, процесс возобновляется, и тогда он сможет читать. Есть режим stty
tostop
, который можно использовать для управления тем, может ли фоновый процесс записывать на терминал, но нет аналогичной опции для чтения, это всегда запрещено.
Если вы хотите, чтобы процесс мог читать с терминала после изменения его группы процессов, вам необходимо изменить группу процессов переднего плана терминала. Это делается с помощью функции tcsetpgrp()
.
tcsetpgrp(0, getpgid(getpid()));
read(2)
разрешен только процессам в группе процессов переднего плана терминала
(это группа процессов, связанная с терминалом в драйвере терминала). Остальные процессы останавливаются, сигнал SIGSTOP
им посылается драйвером tty
. Некоторые управляющие символы также относятся к группе процессов управления терминалом.
См. termios(4)
или tty(4)
для описания управления tty.
Что
ps
показывает статус ребенка после попытки чтения? Я думаю, что ребенку должен быть отправлен сигнал SIGTTIN, который приостановит процесс, если он попытается прочитать с терминала.