The following concepts in Linux kernel are described:
1) Process Group
2) session
3) control terminal
The previous concepts came from our predecessors. I just stood on the shoulders of our predecessors and combined the implementation in the kernel to deepen our understanding of the concepts.
1. concept:
A) Process Group
A command line on Shell forms a process group
Each process belongs to a process group.
Each process group has a leading process
The lifecycle of a process group ends with the last process in the group or ends with another process group.
Getpgrp: Get the process group ID, that is, the PID of the lead Process
Setpgid: add to process group and create new process group
Foreground process group and background process group
========================================================== ========================================================
# Include <unistd. h>
Int setpgid (pid_t PID, pid_t pgid );
Pid_t getpgid (pid_t PID );
Int setpgrp (void );
Pid_t getpgrp (void );
-------------------------------------------------------------------------------
A process can only set itself and its Child processes as process group IDs.
After a sub-process calls the exec function, the ID of the sub-process cannot be used as the ID of the Process Group.
========================================================== ========================================================
B) session
One login form a session
A session can contain multiple process groups, but only one foreground process group can exist.
Setsid creates a new session
========================================================== ========================================================
# Include <unistd. h>
Pid_t setsid (void );
-------------------------------------------------------------------------------
If the called process is not the leading process of the Process Group, this function can create a new session.
After setsid is called, the process becomes the lead process of the new session.
The process becomes the lead process of the new process group.
Process loss control terminal
========================================================== ========================================================
C) control terminal
After a terminal is opened, the terminal becomes the control terminal of the session (svr4/Linux)
The session leader that establishes a connection with the control terminal is called the control process)
One session can have only one control terminal.
Input and signal generated on the control terminal will be sent to all processes in the foreground Process Group of the session
When the connection on the terminal is disconnected (such as network disconnection or modem disconnection), the suspended signal will be sent to the control process (Session leader)
2. Implementation example in Linux to verify the above rules:
Asmlinkage long sys_getpgid (pid_t PID)
{
If (! PID ){
Return Current-> pgrp;
} Else {
Int retval;
Struct task_struct * P;
Read_lock (& tasklist_lock );
P = find_task_by_pid (PID );
Retval =-esrch;
If (P)
Retval = p-> pgrp;
Read_unlock (& tasklist_lock );
Return retval;
}
}
/*
* This needs some heavy checking...
* I just haven' t the stomach for it. I also don't fully
* Understand sessions/pgrp etc. Let somebody who does explain it.
*
* OK, I think I have the protection semantics right... this is really
* Only important on a multi-user system anyway, to make sure one user
* Can't send a signal to a process owned by another.-tyt, 12/12/91
*
* Auch. Had to add the 'did _ exec 'flag to conform completely to POSIX.
* LBT 04.03.94
*/
Asmlinkage long sys_setpgid (pid_t PID, pid_t pgid)
{
Struct task_struct * P;
Int err =-einval;
If (! PID)
PID = Current-> PID;
If (! Pgid)
Pgid = PID;
If (pgid <0)
Return-einval;
/* From this point forward we keep holding onto the tasklist lock
* So that our parent does not change from under us.-davem
*/
Read_lock (& tasklist_lock );
/* Prerequisites: first, verify whether the process to be set exists. If the process does not exist, you cannot do things */
Err =-esrch;
P = find_task_by_pid (PID );
If (! P)
Goto out;
/* Prerequisite: Check the permissions for this operation:
The current process can only set itself and its sub-processes as process group IDs, and
The current process and its Child processes must belong to the same session
(Processes in the same group must belong to the same session)
*/
If (p-> p_pptr = Current | p-> p_opptr = current)
{
Err =-eperm;
/* If it does not belong to the same session (same console), it cannot */
If (p-> session! = Current-> session)
Goto out;
Err =-eacces;
/* After a sub-process calls the exec function, the ID of the sub-process cannot be used as the ID of the Process Group */
If (p-> did_exec)
Goto out;
}
Else if (P! = Current)
Goto out;
Err =-eperm;
/* Boolean value for session group leader */
/* The leader of a session cannot
Note that the leader process of the process group can also change the group ID */
If (p-> leader)
Goto out;
/* GOOD! The following prerequisites are met:
But is the validity of the group number not verified yet? After reading this article! */
/* The process number to be set is not the group number to be set. If yes, set it directly because
This means that a process group with its own PID as the new group number is added.
The process will also become the leader process of the new process group, so there is no need to compare
Session number. You must be the same session for yourself. If the conditions are not met
Make these judgments */
If (pgid! = PID)
{
Struct task_struct * TMP;
For_each_task (TMP)
{
/* Whether a process can be found. The group number is exactly the group number to be set,
And the process to be set belongs to the same Console (same session)
It can be set only when it is found. In fact, this is to determine the validity of the group number,
That is, it must be an existing group and be in the same session as the current one.
You can perform this operation, and you can't forget it. In fact, it means the process in the same group.
Must belong to the same session */
If (TMP-> pgrp = pgid &&
TMP-> session = Current-> session)
Goto OK _pgid;
}
Goto out;
}
OK _pgid:
P-> pgrp = pgid;
Err = 0;
Out:
/* All paths lead to here, thus we are safe.-davem */
Read_unlock (& tasklist_lock );
Return err;
}
Asmlinkage long sys_getsid (pid_t PID)
{
If (! PID ){
Return Current-> session;
} Else {
Int retval;
Struct task_struct * P;
Read_lock (& tasklist_lock );
P = find_task_by_pid (PID );
Retval =-esrch;
If (P)
Retval = p-> session;
Read_unlock (& tasklist_lock );
Return retval;
}
}
Asmlinkage long sys_setsid (void)
{
Struct task_struct * P;
Int err =-eperm;
Read_lock (& tasklist_lock );
For_each_task (P)
{
/* If the current process is the leader process of a process group,
You cannot create a new session */
If (p-> pgrp = Current-> PID)
Goto out;
}
/* Set the leader of the newly created session to the current process as the creator */
Current-> leader = 1;
/* Clearly shows that a new process group has been created
The current process becomes the leader process of the new process group
The ID of the new session is the current process number and the leader of the new session.
*/
Current-> session = Current-> pgrp = Current-> PID;
/* The current process has no control terminal */
Current-> tty = NULL;
Current-> tty_old_pgrp = 0;
Err = Current-> pgrp;
Out:
Read_unlock (& tasklist_lock );
Return err;
}