Linux Course Design Report [Complete Works]

If it helps you, remember to like and follow me!

4 topics: process creation and creation process analysis, process family relationship analysis, inter-process soft interrupt communication, inter-process pipeline communication (comments/private messages are welcome)

The author uses the map made by "ProcessOn Free Online Mapping Website".

Report format requirements: body {Chinese: Times New Roman, No. 5, single-spaced; English: Times New Roman, No. 11, single-spaced}

                        First-level headings {Chroma, small three, bold} Second-level headings {fourth} Third-level headings {small four} No fourth-level headings are allowed

                        Figure name {center below the figure, Song type, No. 5, only allow 2-level figure name eg.3-1 <space> name} Figure text { Song type, small five}

                        table name {center above table,...} table text{...}

                        Header {student number <space> name, vernacular, small four, center} Footer {Roman numerals for table of contents page numbers, Arabic numerals for body page numbers}

                        Note* Reference format requirements, indentation requirements

Topic 1 Process Creation and Creation Process Analysis  Reference Book P163~166

1.1 Design purpose

       Flexible use of the fork system call to create a process, in-depth analysis of the process creation process and the meaning of the return value of the fork system call, and a thorough analysis of the parent-child process code sharing, execution process and data collection change trajectory.

1.2 Design Requirements

       The designed program can reflect the difference in the execution trajectories of the parent and child processes, as well as the difference in the data sets of the parent and child processes.

1.3 Program source code

#include<stdio.h>
#include<unistd.h>
pid_t fork(void);
int main()
{
    printf("parent pid=%d\n",getpid());
    pid_t pid=fork();
    int x=0;
    if(pid==0){
        x=x+1;
        printf("child pid=%d,x=%d,&x=%p\n",getpid(),x,&x);
    }
    else{
        x=x-1;
        printf("parent pid=%d,x=%d,&x=%p\n",getpid(),x,&x);
    }
    sleep(10);
}

1.4 Running results

            Figure 1-1 The running result created by the parent and child processes

1.5 Related Charts

                         Figure 1-2 Schematic diagram of the PCB and data set corresponding to the process

                                 Figure 1-3 How the fork system call creates a process

                      Figure 1-4 The execution path of the parent and child processes after the fork system call returns

Steps:

(1) When the program starts, the system loads the program, allocates memory for variables, creates a process control block PCB for the parent process, and fills in the PID (here 3416) assigned to the process, code address, data set address and other attributes, the contents of x and PID in the process dataset are variable.

(2) The parent process executes the assignment statement "x=0": the program writes the integer 0 to the storage unit where the variable x is located.

(3) The parent process executes the fork system call:

   ①The system first creates the child process PCB, and the content is copied from the parent process PCB, but the pid is the only integer newly allocated (3417 here);

   ②Create a copy of the parent process data set and save it in the newly allocated memory as the child process data set, where the value of the variable x is also 0, and the child process will only operate on its own data set in the future;

   ③ The data set address in the sub-process PCB points to the sub-process's own data set. With the program code, data set and PCB, a complete sub-process is created. In this way, except that the pid of the child process is different from that of the parent process, the program code and data set are the same as those of the parent process, and the fork function completes the copying of the parent process;

   ④ Since the child process is copied from the parent process, the program counter PC has the same address. When the CPU is obtained, the next instruction or statement is also consistent with the parent process, the parent process then returns from the fork system call, and the child process does the same. There is a "fork function return value" item in the data set of the parent and child processes. The return value of the parent process fork system call is the pid of the child process (here, 3417), and the fork return value of the child process is 0, which is filled by the system. into the data set of the parent and child processes.

(4) The execution path of the parent and child processes after the fork system call returns:

   ①After the fork system call completes the creation of the child process, the parent and child processes have the same program code, which starts to execute from the function call return, reads the fork return value from the data set, and assigns it to the pid variable, so the pid variable of the parent process is written. Enter 3417, the pid variable of the child process is written to 0;

   ② Next, the parent and child processes are executed down, judge the if condition, and decide whether to execute the if branch. Since the parent process pid>0 and the child process pid==0, the parent process will enter the if(pid>0) branch, and the child process will enter the if(pid==0) branch;

   ③ When the parent process executes the if (pid>0) branch, it encounters the x=x-1 statement, subtracts 1 from x (the initial value is 0) and writes it back to -1, and outputs "PID of the parent process, x's value and the address of x"; when the child process executes if (pid==0), it encounters the x=x+1 statement, adds 1 to x (initial value 0) and becomes 1, and outputs "PID of the child process. , the value of x and the address of x";

   ④ After the if statement block is completed, both processes must execute the last "sleep(10);" statement, sleep for 10 seconds, so that the user has time to view the process information.

1.6 References

[1] Xu Qingui, Xu Zhigen, Huang Peican, Xie Weipeng. Linux Programming [M]. Beijing: Tsinghua University Press, 2019:163-166.

1.7 Experience

       Through the design of this course, I learned to flexibly use the fork system call to create a process, deeply analyze the process creation process and the meaning of the return value of the fork system call, and thoroughly analyze the parent-child process code sharing, execution process and data collection change trajectory.

       When the fork function is called once, it returns twice. Called once in each of the parent and child processes. The return value in the child process is 0, and the return value in the parent process is the PID of the child process. Depending on the return value, the parent process and the child process can execute different code. The child process is a copy of the parent process and obtains a copy of the parent process data space, heap and stack; the parent and child processes do not share these storage spaces, that is, code segments; therefore, changes made by the child process to variables will not affect the parent process. . Generally speaking, the execution order of the parent and child processes after fork is uncertain, which depends on the kernel scheduling algorithm. Synchronization between processes requires process communication.

Topic 2 Process kinship analysis  , please refer to P166~169

2.1 Design purpose

       Gain the ability to write multi-process concurrent programs by drawing process family relationship diagrams to help understand multi-process applications.

2.2 Design requirements

       Analyze the kinship relationship of the process according to Figure 5-16 in the textbook. Debug, run, and analyze the exercise 5.10 of the textbook, and make appropriate modifications to the program before analyzing the output results.

2.3 Program source code

#include<unistd.h>
int flag=1;
int main(){
    pid_t pid;
    pid=fork();
    if(pid>0)flag=flag+1;
    if(pid==0)flag=flag+2;
    pid=fork();
    if(pid>0)flag=flag+10;
    if(pid==0)flag=flag+20;
    pid=fork();
    if(pid>0)flag=flag+100;
    if(pid==0)flag=flag+200;
    pid=fork();
    if(pid>0)flag=flag+1000;
    if(pid==0)flag=flag+2000;
    printf("flag=%d,pid=%d\n",flag,getpid());
}

2.4 Running results

                  Figure 2-1 The running result of the process family relationship

2.5 Related charts

                         Figure 2-2 Process family relationship analysis and process drawing method

Program execution and process generation process:

(1) When the program starts, the system creates a process p1 (flag=1); p1 executes the first fork function call in the program to create a child process p11 (flag=1), and the pid variable values ​​of the two processes are p11 respectively. PID and 0, ie p1.pid=PID(p11), p11.pid=0.

(2) If the condition pid>0 is true, the process p1 adds 1 to the flag to become 2; if the condition pid==0 is true, the process p11 adds 2 to the flag and turns it into 3.

(3) Then both p1 and p11 execute the second fork function call in the program, creating processes p12 (flag=2) and p111 (flag=3) respectively, and the pid variable values ​​of the four processes are respectively p1.pid=PID (p12), p11.pid=PID(p111), p12.pid=0, p111.pid=0.

(4) Processes p1 and p11 when the condition pid>0 is true add 10 to the flag to become 12 and 13; when the condition pid==0 is true, the processes p12 and p111 add 20 to the flag to become 22 and 23.

(5) The third fork function call and the following two if statements, the execution steps are the same as the steps (3) and (4), abbreviated as:

         p1:flag=12+100=112   p11:flag=13+100=113   p111:flag=23+100=123

         p12:flag=22+100=122  

         New child process p13:flag=12+200=212 p112:flag=13+200=213 p121:flag=22+200=222 p1111:flag=23+200=223

(6) The fourth fork function call and the following two if statements, the execution steps are the same as the steps (3) and (4), abbreviated as:

         p1:flag=112+1000=1112   p11:flag=113+1000=1113   p111:flag=123+1000=1123

         p12:flag=122+1000=1122   p13:flag=212+1000=1212   p112:flag=213+1000=1213   

         p121:flag=222+1000=1222   p1111:flag=223+1000=1223

         New child process p14:flag=112+2000=2112 p131:flag=212+2000=2212   

         p122:flag=122+2000=2122   p1211:flag=222+2000=2222   

         p113:flag=113+2000=2113   p1121:flag=213+2000=2213   

         p1112:flag=123+2000=2123   p11111:flag=223+2000=2223

(7) Finally, the 16 processes all execute printf down, generate 16 lines of output, and execute the sleep(10) statement respectively to sleep for 10 seconds and terminate.

2.6 References

[1] Xu Qingui, Xu Zhigen, Huang Peican, Xie Weipeng. Linux Programming [M]. Beijing: Tsinghua University Press, 2019:166-169.

2.7 Experience

       In this course design, I learned to help understand multi-process applications by drawing process family relationship diagrams, so as to gain the ability to write multi-process concurrent programs.

       The process family relationship diagram allows me to clearly understand the intricate parent-child relationship between processes and how to "reproduce offspring" after the fork system call. The variable flag assigned to generations of descendants will not repeat each other like their inherent PID, which can more uniquely identify a process.

Topic 3 Inter-process soft interrupt communication  , see book P186~193

3.1 Design purpose

       Understand the inter-process softirq communication mechanism.

3.2 Design Requirements

       Use the system call fork() to create two child processes, and then use the system call signal() to let the parent process capture the interrupt signal issued on the keyboard (that is, press the Ctrl+C key), when the parent process receives one of these two soft interrupts After that, the parent process uses the system call kill() to send soft interrupt signals with integer values ​​of 16 and 17 to the two child processes, respectively. The child process obtains the corresponding soft interrupt signal, and then terminates after outputting the following information:

       Child process 1 is killed by parent!!

       Child process 2 is killed by parent!!

       After the parent process calls the wait() function to wait for the termination of the two child processes, it outputs the following information to end the process execution:

       Parent process is killed!!

       Run the program written several times and briefly analyze the reasons for the different results.

3.3 Program source code

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int flag_wait = 1;
void stop2()
{
    flag_wait = 0;
    printf("Child interruption\n");
}
void stop1()
{
    printf("Parent interruption\n");
}
int main()
{
    pid_t pid1, pid2;
    //当接受到按下Ctrl+C时产生的SIGINT信号时,调用stop1()
    signal(SIGINT, stop1);
    //创建子进程1
    do
    {
        pid1 = fork();
    } while (pid1 < 0);
    if (pid1 > 0)
    {
        //创建子进程2
        do
        {
            pid2 = fork();
        } while (pid2 < 0);
        if (pid2 > 0)
        {
            sleep(5);
            //向子进程1发送中断信号16
            kill(pid1, 16);
            wait(0);
            //向子进程2发送中断信号17
            kill(pid2, 17);
            wait(0);
            printf("Parent process is killed!!\n");
            exit(0);
        }
        else
        {
            //当接受到信号17时,调用stop2()
            signal(17, stop2);
            //死循环直到接收到中断信号
            while (flag_wait);
            printf("Child process 2 is killed by parent!!\n");
            exit(0);
        }
    }
    else
    {
        //当接受到信号16时,调用stop2()
        signal(16, stop2);
        //死循环直到接收到中断信号
        while (flag_wait);
        printf("Child process 1 is killed by parent!!\n");
        exit(0);
    }
    return 0;
}

3.4 Running results

Figure 3-1 Automatic running result after 5 seconds of execution

Figure 3-2 The running result after pressing Ctrl+C during execution

Program execution steps:

(1) Create two pid_t type variables pid1 and pid2;

(2) Then use the system call signal() to let the parent process capture the interrupt signal issued on the keyboard (ie press Ctrl+C key)

①When the parent process receives this soft interrupt (Ctrl+C), it outputs "Parent interruption";

② When the parent process does not receive a soft interrupt (Ctrl+C), it continues to execute;

(3) The fork system call creates child processes pid1 and pid2;

(4) If the child processes pid1 and pid2 are currently running, they will terminate after they get the soft interrupt signal, and output "Child process 1 is killed by parent!!", "Child process 2 is killed by parent!!";

(5) If the parent process is currently running, sleep together for 5 seconds, and then send interrupt signals 16 and 17 to child processes 1 and 2 respectively. The parent process calls the wait() function to wait for the termination of the two child processes, and outputs "Parent" process is killed!!" to end the process execution.

3.5 Related Charts

                                    Figure 3-3 Flowchart of soft interrupt communication between processes

3.6 References

[1] Xu Qingui, Xu Zhigen, Huang Peican, Xie Weipeng. Linux Programming [M]. Beijing: Tsinghua University Press, 2019:186-193.

3.7 Experience

       Through the design of this course, I understand the inter-process soft interrupt communication mechanism. Soft interrupt signal (signal) is a simple and basic process communication mechanism, its biggest feature is to provide a simple way to deal with asynchronous events. For example, a common user types the key combination Ctrl+C from the keyboard to interrupt the running of a program, or a signal between two processes is used to notify the occurrence of an asynchronous event, or a sudden hardware failure is reported to the system or process, Such as illegal instructions, operation overflow, etc. More importantly, the user process can also send a signal to itself to interrupt the execution of the process, and automatically transfer to the specified soft interrupt processing function to execute the processing content arranged by the user, and then return to the user process to continue execution after the processing is completed. The application provides a communication mechanism to handle random events by the user.

       A softirq signal implementation is a mechanism used by the operating system to notify a process that something has happened. Since this kind of signal always responds when the process is running, it is called a soft interrupt signal. The user of the soft interrupt signal is the operating system and the source program. The operating system encodes the software interrupt signal that can be used in the system in advance and defines the corresponding meaning, and then submits it to the user for use. The user can use the soft interrupt through the corresponding software interrupt serial number or soft interrupt name, and the two are equivalent in use. The user can only use the software interrupt signal within the range of the software interrupt serial number provided by the operating system, and cannot create a new software interrupt signal by himself. If there is a signal to be sent between the user's applications, the user signal SIGUSR1 or the user signal SIGUSR2 reserved by the operating system for the user can be used.

Topic 4 Pipeline communication between processes,  see book P278~281

4.1 Design purpose

       Understand the inter-process pipe communication mechanism.

4.2 Design Requirements

       Use the system call pipe() to establish a pipeline, and the two subprocesses write a sentence to the pipeline:

       Child process1 is sending a message!

       Child process2 is sending a message!

       The parent process reads the information from the two child processes from the pipe and displays it on the screen.

       Requirement: The parent process first accepts the message sent by the child process P1, and then accepts the message sent by the child process P2.

4.3 Program source code

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
int main()
{
    pid_t pid1,pid2;  //定义两个进程变量
    int fd[2];
    char OutPipe[100],InPipe[100];  //定义两个字符数组
    pipe(fd);  //创建管道
    while((pid1=fork())==-1);  //如果进程1创建不成功,则空循环
    if(pid1==0)  //如果子进程1创建成功,pid1为进程号
    {
        lockf(fd[1],1,0);  //锁定管道
        sprintf(OutPipe,"Child process 1 is sending message!\n");  //给OutPipe赋值
        write(fd[1],OutPipe,50);      //向管道写入数据
        sleep(1);  //等待读进程读出数据
        lockf(fd[1],0,0);  //解除管道的锁定
        exit(0);  //结束进程1
    }
    else
    {
        while((pid2=fork())==-1);  //若进程2创建不成功,则空循环
        if(pid2==0)
        {
            lockf(fd[1],1,0);
            sprintf(OutPipe,"Child process 2 is sending message!\n");
            write(fd[1],OutPipe,50);         
            sleep(1);
            lockf(fd[1],0,0);
            exit(0);
        }
        else
        {
            wait(0);  //等待子进程1结束
            read(fd[0],InPipe,50);  //从管道中读出数据
            printf("read:%s\n",InPipe);  //显示读出的数据
            wait(0);  //等待子进程2结束
            read(fd[0],InPipe,50);
            printf("read:%s\n",InPipe);  //父进程结束
            exit(0);
        }
    }
    return 0;
}

4.4 Running Results

             Figure 4-1 The running result of inter-process pipeline communication

4.5 Related Charts

Figure 4-2 Flow chart of pipeline communication between processes

4.6 References

[1] Xu Qingui, Xu Zhigen, Huang Peican, Xie Weipeng. Linux Programming [M]. Beijing: Tsinghua University Press, 2019:278-281.

4.7 Experience

       Through the design of this course, I understand the inter-process soft pipe communication mechanism.

       A pipe, also known as a pipe file, is used to connect a reading process and a writing process to achieve information sharing between them. The sending process (that is, the writing process) that provides input to the pipe (shared file) sends a large amount of data into the pipe in the form of a character stream; and the receiving process (that is, the reading process) that accepts the output of the pipe can receive (read) from the pipe. data.

        In order to coordinate the communication between the two parties, the pipeline mechanism must provide the following three aspects of coordination:

       (1) Mutual exclusion: When a process is performing read/write operations on the pipe, other (another) processes must wait, and the program uses the lockf(fd[1],1,0) function to lock the pipe. , unlock the pipeline with lockf(fd[1],0,0).

       (2) Synchronization: When the write (input) process writes a certain amount (such as 4KB) of data into the pipe, it goes to sleep and waits until the read (output) process takes the data, and then wakes it up. When the reading process tries to read data from an empty pipe, it should also sleep and wait until the writing process writes data to the pipe before waking it up.

       (3) Determine whether the other party exists: Only when it is determined that both the writing process and the reading process exist, can communication be performed through the pipeline.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324143353&siteId=291194637