Experiment 1 of Linux operating system: Process Management

Experiment 1 of Linux operating system: Process Management

Title:

[purpose]

Master the use of Linux operating system; Master the C program development method under linux environment;
Deepen the understanding of the concept of process and further understand the essence of concurrent execution; Learning is performed through processes
Method of new target program; Understand the basic principle of process signal processing in Linux system; Master make
How to use the tool.

[experimental preparation content]

(1) Learn how to use Linux operating system; C language programming method, compiled under Linux
Methods of debugging and running C program; Understand the difference between process and program and the concept of concurrent execution.
(2) Understand the function of the system call fork() and analyze the process creation process.
(3) Read the reference materials of relevant chapters: the use of make; Process control; Signal. deepen
Understanding of the concept of process management.

[experiment content]

Read the relevant references in the basic chapter, process control, signal and other chapters, and analyze the sample program
Code, familiar with the experimental environment, written in C language, including the following four requirements.

  • Compile and use make tool;
  • The code uses the fork function;
  • The code uses the exec function;
  • The code uses the signal function or the sigaction function.

1, Experimental environment:

Oracle VM VirtualBox,Ubuntu(64-bit)

2, Experiment content:

Code part:

gx1.c

/*gx1.c*/
/*
The code calls two times fork to create two sub processes.
The first subprocess calls execv to compile, and the second subprocess calls execl to execute the program
 During this process, the parent process will block itself and wait to catch the child process that becomes a zombie process.
*/

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

int main(void)
{
    char *arg1[]={"gcc","-o","gx2","gx2.c",NULL};
    pid_t pid,pr;                                               /*Process identifier*/
    if((pid=fork())<0)                                          /*Create the first child process*/
    {
        perror("fork");                                         /*error handling*/
        printf("The first child process creation failed.");
        exit(0);
    }
    if(pid==0)
    {
        sleep(3);
        printf("The first sub process was created successfully\n");
        if((execv("/bin/gcc",arg1))==-1)                        /*Go to compile gx2.c and judge whether there is an error*/
        {
            perror("execv");                                        /*error handling*/
            printf("The first attempt to call the process failed\n");
		    exit(0);
        }
    }
    if((pid=fork())<0)                                          /*Create second child process*/ 
    {
        perror("fork");                                         /*error handling*/
        printf("The second child process creation failed\n");
        exit(0);
    }
    else if(pid==0)
    {
        sleep(5);
        printf("The second child process was created successfully\n");
        if((execl("/home/gaoxu/ex1/gx2","",NULL))==-1)          /*Go to execute the program gx2 and determine whether there is an error*/
        {
            perror("execl");
            printf("The second attempt to call the process failed\n");
		    exit(0);
        }
        
    }
    else
    {
        printf("Identifier is%d The parent process of is waiting to catch the zombie process\n",pid);
        pr=wait(NULL);                                          /*The parent process blocks itself and collects zombie process information*/
        printf("The parent process successfully captured the zombie process with identifier%d\n",pr);
    }
    return 0;
}

gx2.c

/*gx2.c*/
/*The code implementation executes an endless loop when no SIGINT or SIGQUIT signal is received*/

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

int wait_mark=1;

void hangup()
{
	while(wait_mark==1);
}

void Newhandler1(int iSignNo,siginfo_t *pSignInfo, void *pReserved)
{
    printf("receive SIGINT Signal, enter signal processing function Newhandler1,signo:%d.\n",iSignNo);
    wait_mark=0;                                                                    /*Terminate the dead cycle*/
    printf("Leave signal processing function Newhandler1,signo:%d\n",iSignNo);
}

void Newhandler2(int iSignNo,siginfo_t *pSignInfo, void *pReserved)
{
    printf("receive SIGQUIT Signal, enter signal processing function Newhandler2,signo:%d.\n",iSignNo);
    wait_mark=0;                                                                    /*Terminate the dead cycle*/
    printf("Leave signal processing function Newhandler1,signo:%d\n",iSignNo);
}

int main(void)
{
    struct sigaction act1,act2;                                                     /*Structure containing signal processing actions*/
    act1.sa_sigaction=Newhandler1;                                                  /*Specify signal processing function*/
    act2.sa_sigaction=Newhandler2;                                                  
    act1.sa_flags=SA_SIGINFO;                                                       /*Indicates that the signal processing function is composed of sa_sigaction specifying*/
    act2.sa_flags=SA_SIGINFO;                                                       
    sigemptyset(&act1.sa_mask);                                                     /*Signal set processing function, act.sa_ The signal set pointed to by the mask is cleared,*/
    sigemptyset(&act2.sa_mask);                                                     /*That is, it does not contain any signal*/
    sigaction(SIGINT,&act1,NULL);                                                   /*Register SIGINT signal*/
    sigaction(SIGQUIT,&act2,NULL);                                                  /* Register SIGQUIT signal*/
    hangup();                                                                       /*Waiting signal*/
    pid_t pid=getpid();                                                             /*Get process ID*/
    printf("Identifier is%d The child process of has been killed\n",pid);
    exit(0);
    return 0;
}

Result screenshot:

3, Experiment summary:

1. Procedural thought:

flow chart:


As shown in the figure above, gx1.c and gx2.c files are compiled for this experiment,

① In gx1.c, fork function, sleep function, exec function family and wait function are used

Realized
(1) fork generates a sub process, which calls execv function to compile gx2.c
(2) Thirdly, fork generates a sub process and calls execl function to run the gx2 program. sleep function is used to realize synchronization to avoid calling the running program command first and then the gcc compilation command.
(3) The parent process uses the wait function to wait for the end of the life cycle of the first child process and catch the zombie process.

② The sigaction function is used in gx2.c to define hangup dead loop function, Newhandler1 and Newhandler2 signal processing functions.

Realized
(1) When the SIGINT signal and SIGQUIT signal are not received, execute the hangup function to enter the dead loop.
(2) After receiving SIGINT signal or SIGQUIT signal, the signal processing function clears the dead cycle parameters and kills the process.

2. Self taught knowledge of this experiment:

① fork function

② exec function family

③ wait function

④ signal function

⑤ sigaction function

⑥ make tool

⑦ Concurrent execution of Linux

⑧ Process management and communication in Linux

3. Problems encountered and solutions:

① Drag the Makefile.txt tool into the virtual machine and use the make command to report an error. make: *** No targets specified and no makefile found. Stop

Solution: by querying the data, we know that the error is because the make command cannot find the file named makefile or makefile.
First, try to specify the file name as makefile. An error is reported again. It is speculated that the txt file may not be a makefile file.
Finally, the vi Makefile command is used to write the Makefile file directly in the Linux virtual machine.

② Using the exec function cannot compile other. c files and execute them.

Solution: according to the information,
Call the gcc compilation command pathname. The path should be specified as the location of the gcc file in the root directory. This experiment is / bin/gcc.
Calling an executable program with execl should give the complete full path: / home/gaoxu/ex1/gx2. Even if the program has no parameters, it cannot end with NULL directly. The "" NULL character should be added before NULL.

③ execl calls the program gx2, but gx2 cannot receive the signal of ctrl+c or ctrl + \ given by the keyboard.

Solution: ask the teacher after long time no fruit, guess that the ctrlc signal or ctrl\ signal triggered by the keyboard can only be sent to the current foreground process. The reason may be that the program that is invoked in the program will be turned into background running. Using ps, we can see that gx2 has been running in the system, sending SIGINT signal or SIGQUIT signal at the terminal using kill Command. gx2 process can also be killed normally.

Tags: C C++ Linux

Posted on Thu, 23 Sep 2021 20:33:20 -0400 by kituscat