Inter-process relationship (part 1)

Interprocess relationship

introduction

This chapter details the concept of linux sessions. The relationship between the login shell and all processes started from the login shell will also be introduced.

9.2 Terminal login

In the early unix systems, users used dumb terminals to log in, and the hardware was directly connected to the server. The terminal is local or remote, and the login is performed by the terminal device driver in the kernel.

With the emergence of bit-mapped terminal images, in addition to window systems, some platforms automatically start window systems for users.

1. BSD terminal login

自举一词来自于人都是靠自身的“自举”机构站立起来的这一思想。计算机必须具备自举能力将自己所与的元件激活,以便能完成加载操作系统这一目的,然后再由操作系统承担起那些单靠自举代码无法完成的更复杂的任务。



自举只有两个功能:加电自检和磁盘引导。  加电自检:当我们按下计算机电源开关时,头几秒钟机器似乎什么反应也没有,其实,这时的计算机正在进行加电自检,以断定它的所有元件都在正确地工作。如果某个元件有故障,显示器上就会出现报警提示信息(如果显示器也不能正常工作,则以一串嘟嘟声来报警)。由于大多数计算机工作非常可靠,加电自检报警非常罕见。   磁盘引导:查找装有操作系统的磁盘驱动器。从磁盘加载操作系统的原因有二:一是操作系统升级简单容易,二是使用户拥有选择操作系统的自由。当以上功能完成时,自举操作就启动一个读写操作系统文件和将它们复制到随机存储器中的过程,此时的机器才是真正意义上的计算机。计算机的启动可以有冷启动和热启动两种方式 ,它们之间的差别是热启动不进行机器的自检(机器本事配置的检查与测试),当计算机在使用过程中由于某些原因造成死机时,可以对计算机进行热启动处理

System administrators usually create a file named /etc/ttys, each terminal has a line, each line describes the device name and the parameters passed to getty.

When the system boots, the kernel creates a process with id 1, which is the init process. The init process causes the user to enter multi-user mode. Init reads /etc/ttys for each device terminal that is allowed to log in. Init calls fork once, and the child process it generates is the exec getty program.

Getty calls the open function on the terminal device to open the terminal in a read-write mode. If it is a modem, open may be stuck in the driver until the user dials the number. Once the device is opened, the descriptor 0.1.2 will be reset to this device. Getty returns login and waits for user input. If the terminal supports multiple speeds, getty can support multiple speeds, and getty can test special characters to change the terminal speed. If the user enters a username, getty calls login in the following way

execle("/bin/login", "login", "-p", username, (char*)0, envp);

init calls getty with an empty environment. Getty creates an environment with the terminal name and the environment string login. The -p flag tells login to keep the environment passed to him. You can also add other strings to the environment, but don't replace him.

The general process is

Call getpwname to obtain the corresponding user password file login entry. Then call getpass to display the call password, and then read the password entered by the user. Call crtpt to encrypt the password, and then compare it with the shadow file. If you don't enter it for several times, exit will exit.

Teach the new linux system to use PAM pluggable authentication module.

If the user logs in correctly under PAM, the following things will be done:

1.将当前的工作目录更改为起始目录,chdir

2.调用chown更改终端的所有权,使登录用户成为他的所有者

3.对终端设备的访问权限改为读写

4.调用setgid以及initgroups设置进程组id。

5.用login得到所有信息的初始化环境:起始目录、shell、用户名以及系统默认路径

6.login进程更改为登录用户的uid,setuid并将该用户设置为登录的shell。就好像调用了execl("/bin/sh","-sh",(char*)0)

setuid will change the actual user id, the effective user id will save the user id

9.3 Network login

1. BSD network login

In BSD, there is an inted process waiting for most network connections.

Init calls the shell, making the shell call /etc/rc, thus inted becomes a daemon process, once the shell stops, the inted parent process becomes init. inted waits for tcp connection, once there is a request, fork once, and then call exec

General process

init->inetd->fork+exec(telnetd)和客户端交换数据

The beginning is to use a process to make a pseudo terminal.

9.4 Process Group

In addition to a process id, each process also has a process group id. getpgrp returns the process group id of the calling process. A process group is a collection of one or more processes. Write a demo

#include <unistd.h>
#include <iostream>

int main()
{
    std::cout<<getpgrp()<<std::endl;
}

If there is only one main process, it is usually itself

getpgid returns the process group id of the process, the process group id is the process id #include <unistd.h> #include

int main()
{
    pid_t pid = getpid();
    std::cout<<(pid)<<std::endl;
    std::cout<<getpgid(pid)<<std::endl;
}

The output is the same process id and process group id

setpgid can add a process to a process group or setsid can also create a process group

setpgid(pid_t pid,pid pgid);

The setpgid function sets the process group id of the pid process to pgid. If these two parameters are equal, the process specified by pid becomes the process group leader. If pid is 0, the process id of the caller is used. If pgid is 0, the process id of the caller is used as the process group id.

Used to create a new process group

Most job-controlled shells will call this function to make the parent process set the process group id of its child process, and also make the child process set its own process group id. One of these two calls is redundant, but letting both the parent process and the child process do so can ensure that this has indeed happened before the parent process and the child process think that the child process has entered the group. If you don't do this, after the fork, because the execution sequence of the parent and child processes is uncertain, race conditions will occur because the membership of the child process depends on which process is restrictive.

The function above is a very interesting function, we can write a few demos to study

#include <unistd.h>
#include <iostream>
#include <wait.h>
#include <unistd.h>

int main()
{
    int status;

    pid_t son_pid = fork();
    pid_t parent_pid = getpid();
    if(son_pid == 0)
    {
        setpgid(0, getpid());

        //son
        printf("son-pid:%d;group id:%d\n",getpid(),getpgrp());

        pid_t _son_pid = fork();
        if(_son_pid == 0)
        {
            printf("son son group id:%d\n",getpgrp());
            while(1)
            {

            }
        }else if(_son_pid > 0)
        {
            waitpid(_son_pid, &status, 0 );
        }
    }else if(son_pid > 0)
    {
        sleep(3);
        printf("parent-pid:%d;group id:%d\n",parent_pid,getpgrp());
        //parent
        waitpid(son_pid, &status, 0 );
    }

}

We use ps aux to observe the id of this process group /home/zhanglei/ourc/test/cmake-build-debug/test son-pid:11207;group id:11207 son son group id:11207 parent-pid:11206;group id:11206

The setpgid function has many limitations:

·pid参数必须指定为调用setpgid函数的进程或其子进程,不能随意修改不相关进程的进程组ID,如果违反这条规则,则返回-1,并置errno为ESRCH。
·pid参数可以指定调用进程的子进程,但是子进程如果已经执行了exec函数,则不能修改子进程的进程组ID。如果违反这条规则,则返回-1,并置errno为EACCESS。
·在进程组间移动,调用进程,pid指定的进程及目标进程组必须在同一个会话之内。这个比较好理解,不加入公司(会话),就无法加入公司下属的部门(进程组),否则就是部门要造反的节奏。如果违反这条规则,则返回-1,并置errno为EPERM。
·pid指定的进程,不能是会话首进程。如果违反这条规则,则返回-1,并置errno为EPERM

I used this demo to see that the program is correct. The child process sets the id of the process group to himself, so it becomes two process groups.

Go here first and continue reading down.

9.5 sessions

A session is a collection of one or more process groups

The process calls the setsid function to establish a new session.

#include <unistd.h>
pid_t setsid

If the call is not the leader of the process group, then this function will create a session. Specifically, the following three things will happen.

1) This process will become the first process of the session. At this time, the process is the only process in this session.

2) This process will become the leader process of the new process group.

3) The process has no terminal control. If there is a terminal control before calling setsid, the connection will also be cut off.

If the call is the leader of the process group, it will fail. Generally, after fork the parent process, the parent process is killed, and the child process gets a brand new process id, which ensures that this process will not be the leader of the process group.

getsid(pid_t pid)

If pid is 0, getsid returns the process group id of the first process in the session of the calling process. If the called pid does not belong to the caller's session, then the process cannot get the process group id of the first process of the session.

Guess you like

Origin blog.csdn.net/qq_32783703/article/details/107238355