Process Relationships
Process Group
A process group is a collection of one or more processes. Typically, they are combined in the same job, and each process in the same process group receives various signals from the same terminal, each with a unique process group ID. Each process group has a leader process , and the ID of the leader process is equal to the process group ID. The time from the start of a process group creation to the end of the last process is called the life cycle of the process group.
#include <unistd.h> pid_t getpgrp (void); return value: process group ID of the calling process int Setpgid (pid_t pid, pid_t pgid); return Value: success, return 0, failure, return-1 Description Setpgid is used to add a process to an existing process group, or to create a new process group. The function adds a process ID of PID to the process group with ID pgid. if pid = = Pgid, then the PID specified process becomes the process leader; If pid = = 0, the caller's process ID is used; If Pgid = = 0, the PID is used as the process group ID. |
Session
A session is a collection of one or more process groups . A process group is typically composed of shell pipelines, as follows:
Proc1 | PROC2 & PROC3 | proc4 | Proc5 |
The process calls the SETSID function to create a new session:
#include <unistd.h> pid_t setsid (void); return Value: success, return process group ID; failed, return-1 Description If the process calling this letter is not a process leader, this function creates a new session, as follows: (1) The process becomes the session first process of the new session. (2) The process becomes the constituent process of a new process group, and the new process group ID is the process ID. (3) The process does not control the terminal. pid_t getsid (pid_t pid); return value: successful, returns the process group ID of the session's first process; failed, return-1 Description GETSID (0) returns the process group ID of the session's first process that called the process, and does not return if the PID is not part of the session where the caller resides. |
Control Terminal
A session can have a control terminal, usually an end-device or pseudo-terminal device. The first process of establishing a session connected to a control terminal is called the control process . A group of processes in a session can be divided into a foreground process group and a background process Group. There needs to be a way to tell the kernel which process group is the foreground process group, so that the end device driver knows where to send the signal from the terminal input and terminal:
#include <unistd.h> pid_t tcgetpgrp (int fd); return Value: success, return to foreground process group ID; failed, return-1 int tcsetpgrp (int fd, pid_pgrpid); return Value: success, return 0, failure, return-1 Description Where FD is the associated open terminal. Most applications do not call these two functions directly, but are called by the job control shell. An application that needs to manage the control terminal can call the TCGETSID function to get the process group ID of the session first process that controls the terminal: #include <termios.h> pid_t tcgetsid (int fd); return value: successful, returns the process group ID of the session's first process; failed, return-1 |
Job Control
Job control allows you to start multiple jobs (process groups) on one terminal, which jobs can access the terminal, and which jobs run in the background. From the point of view of the shell using job control, a user can start a job in the foreground or in the background, for example:
VI Main.c starts a job that consists of only one process in the foreground, and makes all & starts a job that consists of only one process in the background.
We can type 3 special characters to make the terminal program generate signals and send them to the foreground process group:
The interrupt character (Ctrl + C) generates a SIGINT signal;
The exit character (Ctrl + \) produces a sigquit signal;
The pending character (Ctrl + Z) produces a SIGTSTP signal;
Only the foreground job can receive the characters entered on the terminal, if the background job tries to terminal, then the terminal driver sends a specific signal sigttin to the background job, the signal will stop this background job, and the shell sends a notification to the user. The user can then use the shell command FG to turn this job into a foreground job run. But what happens if background jobs are output to the control terminal? We can prohibit this situation by stty order. At this point, the terminal driver sends a SIGTTOU signal to the background job to block its process, and of course we can also use FG to move it to the foreground.
Daemon Process
The daemon (daemon) often starts when the system boots and terminates when the system shuts down. Because the daemon does not control the terminal (its terminal name is set to?), it runs in the background. Most daemons are executed with super user privileges.
Programming Rules
(1) First call Umask to set the file mode creation mask to a known quantity value (usually 0). This is done to prevent inherited masking words from having certain permissions, especially write permissions.
(2) Call fork and then exit the parent process.
(3) Call Setsid to create a new session.
(4) Change the current working directory to the root directory. Because the daemon usually exists before the system boots, the file system cannot be uninstalled if the current working directory of the daemon is on a file system that needs to be mounted. There are also certain daemons that change the current working directory to a specified location, such as the line printer spool daemon, which may change its working directory to their spool directory.
(5) Close file descriptors that are no longer needed. You can use the Open_max function or the Getrlimit function to get the highest file descriptor value, and then close all file descriptors until that value. Doing so prevents the daemon from inheriting any file descriptors from its parent process.
(6) Some daemons point the file descriptor 0, 1, and 2 to/dev/null. This allows any program that attempts to read standard input, write standard output, and write standard error output with a spoof, without producing any effect. Because the daemon is running in the background, the termination of the logon session does not affect the daemon. If other users log on on the same terminal, we naturally do not want to see the output of the daemon on that terminal, and the user does not want their input on the terminal to be read by the daemon, so the above measures are quite useful.
The following program can be called by the program to initialize the daemon, call the function daemonize in the main function, and then put the main process into hibernation, through the PS–EFJ name to view the status of the process, you can find the daemon init, its terminal name is?.
[email protected] process]# cat init.c#include<stdio.h>#include<signal.h>#include<unistd.h>#include<syslog.h>#include<fcntl.h>#include<sys/resource.h>voidDaemonize (Const Char*cmd) { intI, fd0, FD1, FD2; pid_t pid; structRlimit RL; structsigaction sa; /* * * Clear file creation mask. * */Umask (0); /* * Get Maximum number of file descriptors. * * */ if(Getrlimit (Rlimit_nofile, &RL) <0) {printf ("%s:can ' t get file limit\n", CMD); return ; } /* * * become a session leader to lose controlling TTY. * * * if(PID = fork ()) <0) {printf ("%s:can ' t fork\n", CMD); return ; } Else if(PID! =0)/*Parent*/Exit (0); Setsid (); /* * * Ensure future opens won ' t allocate controlling ttys. * * *Sa.sa_handler=sig_ign; Sigemptyset (&sa.sa_mask); Sa.sa_flags=0; if(Sigaction (SIGHUP, &sa, NULL) <0) {printf ("%s:can ' t ignore sighup\n", CMD); return ; } if(PID = fork ()) <0) {printf ("%s:can ' t fork\n", CMD); return ; } Else if(PID! =0)/*Parent*/Exit (0); /* * Change the current working directory to the root so * * We won ' t prevent file Systems from being unmounted. * */ if(ChDir ("/") <0) {printf ("%s:can ' t change directory to \ n", CMD); } /* * Close all open file descriptors. * * */ if(Rl.rlim_max = =rlim_infinity) Rl.rlim_max=1024x768; for(i =0; i < Rl.rlim_max; i++) Close (i); /* * * Attach file descriptors 0, 1, and 2 to/dev/null. * * *fd0= Open ("/dev/null", O_RDWR); FD1= DUP (0); FD2= DUP (0); /* * * Initialize the log file. * * */openlog (cmd, log_cons, Log_daemon); if(Fd0! =0|| Fd1! =1|| Fd2! =2) {syslog (Log_err,"unexpected file descriptors%d %d%d", Fd0, FD1, FD2); Exit (1); }}intMainvoid) {daemonize ("PS"); Sleep ( -); return 0;} [email protected] process]#. / init[[email protected] process]# PS - efjUID PID PPID pgid SID C stime TTY time Cmdroot1 0 1 1 0 +: *?xx:xx:Geneva/sbin/Initroot2198 2174 2198 2057 0 +: -pts/0 xx:xx:xxvim init.croot 2237 1 2236 2236 0 19:45? 00:00:00./ initroot2238 2188 2238 2100 0 +: $pts/1 xx:xx:xxPs-efj
Linux Process (ii): Process relationships and their daemons