Linux system programming - process creation (fork), external program call (exec)

1. Introduction to fork function

fork function is a very important function in linux. It can create a new process from an existing process. The new process is a child process and the original process is a parent process.

The return value of fork function is as follows:
1. In the parent process, fork returns the PID number of the newly created child process.
2. In the subprocess, fork returns 0;
3. If an error occurs, fork returns a negative value.
Therefore, the return value can be used to determine whether it is a parent process or a child process.

The fork function creates a child process:
The child process obtained by using the fork function is a replica of the parent process. It inherits all the resources of the process from the parent process, which is equivalent to a copy of the parent process.

#include <unistd.h>
pid_t fork(void); Make split
 Function function: Create a new child process. The child process is a copy of the parent process. (Separation)
Return value:  >0 Represents the parent process  ==0 Represents a child process

Example code:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
    int a=888;
    //Create a new child process
    pid_t pid=fork();
    if(pid==0) //Subprocess
    {
        a=999;
        printf("Subprocess_a=%d\n",a);
        printf("Of child processes PID number:%d\n",getpid());
        printf("Parent process of the current child process PID number:%d\n",getppid());
    }
    else
    {
        sleep(1);
    }
    return 0;
}

2. wait function

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
Function function: Randomly wait for a child process to exit.
If the waiting child process ends normally,The return value is the value of the child process pid number
 If the parent process has no children, the process is running,wait The function returns immediately,The return value is-1

pid_t waitpid(pid_t pid, int *status, int options);
Function function: Wait for the specified child process to exit.

In normal multi process concurrent design, the parent process is responsible for cleaning up the space of the child process:

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

int main()
{
    pid_t pid=fork();
    if(pid==0)
    {
        printf("The subprocess ran successfully.pid=%d\n",getpid());
    }
    else
    {
        pid=wait(NULL); //Wait for the child process to exit and clean up the space of the child process
        printf("Of the child process that exited pid=%d\n",pid);
    }
    return 0;
}

3. exec series functions

exec series functions are used to start a new process. After the new process is successfully started, it will overwrite the original process

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);

p Indicates support for searching executable files from environment variables.

Example code:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
    //ls -l
    //execl("/bin/ls","ls","-l",NULL);
    //execlp("ls","ls","-l",NULL);

    char *cmd[]={"ls","-l",NULL};
    //execv("/bin/ls",cmd);
    //execvp("ls",cmd);

    char *cmd_path[]={"wbyq=666","abcd=888",NULL};
    execle("/bin/ls","ls","-l",NULL,cmd_path);

    printf("exec Function execution failed.\n");
    return 0;
}

4. system function

The system function is used to start a new sub process. This function is internally implemented by using the combination of fork+exec+wait functions.
This indicates that the system function is blocked. You must wait for the execution of the child process before executing the code of the parent process.

#include <stdlib.h>
int system(const char *command);

Example code:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
    printf("Start execution.\n");
    system("sleep 5");
    printf("end of execution.\n");
    return 0;
}

5. popen function

#include <stdio.h>
FILE *popen(const char *command, const char *type);

Function function: start a new process - similar to fopen --dup2 function
The pointer to the return value of successful startup points to the standard output of the process.

int pclose(FILE *stream);
Function function: Free up space
 Sample code:
#include <stdio.h>
int main()
{
    FILE *fp;
    char buff[1024+1];
    int cnt;
    fp=popen("/bin/ls *.sh","r");
    cnt=fread(buff,1,1024,fp);
    buff[cnt]='\0';
    printf("buff=%s\n",buff);
    pclose(fp);
    return 0;
}

6. pkill command

(1) pkill Command supports killing all processes of a user at one time.
$ pkill -u <user name>
(2) pkill The command supports killing all processes with the specified name at once.
$ pkill <apply name>
(3) use killall Command kills all processes with the specified name at once
$ killall <apply name>
(4) Kill all child processes created by the parent process
pkill -9 -P <Parent process PID>

7. Case: use the fork function to create five sub processes to run at the same time

#include <stdio.h>
#include <unistd.h>

int main()
{
    int i;
    pid_t pid;
    for(i=0;i<5;i++)
    {
        pid=fork(); //Create a child process
        if(pid==0)break; //If it is a child process, it will exit the loop directly
    }
    if(i==5) //Parent process
    {
        sleep(5);
        char cmd_buff[100];
        sprintf(cmd_buff,"pkill -9 -P %d",getpid());
        system(cmd_buff);
        while(1)
        {
            pid=wait(NULL);
            if(pid==-1)break; //When the parent process has no child process, the function returns - 1
            else printf("%d Subprocess exited successfully.\n",pid);
        }
        printf("The parent process ended normally.\n");
    }
    else //Subprocess
    {
        while(1)
        {
            sleep(1);
            printf("Currently running child processes pid=%d\n",getpid());
        }
    }
    return 0;
}

8. Case: realize automatic switching (2 seconds) to display all pictures in the specified directory

Use the eog command to make a ppt playback effect with the process knowledge points learned today.
Idea: the parent process scans the directory and gets the file name under the directory. After passing it to the child process, the child process calls the eog command to realize the picture display. After 2 seconds in the parent process, the child process is killed, and then the next file under the directory is read and passed to the child process

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
    if(argc!=2)
    {
        printf("./a.out <Picture catalogue/>\n");
        return 0;
    }
    /*1. Open Directory*/
    DIR *dir=opendir(argv[1]);
    if(dir==NULL)
    {
        printf("%s Directory open failed.\n",argv[1]);
        return 0;
    }
    /*2. Create a pipe file*/
    int fds[2];
    pipe(fds);

    pid_t pid;
    struct dirent *dir_info;
AA:
    /*Loop through directory*/
    dir_info=readdir(dir);
    if(dir_info==NULL)
    {
        printf("The picture is displayed.\n");
        exit(0); //Indicates that the picture is displayed
    }
    /*Create child process*/
    pid=fork();
    if(pid==0) //Subprocess
    {
        char file_name[100+1];
        int cnt;
        //Read data from the reading end of the pipe
        cnt=read(fds[0],file_name,100);
        file_name[cnt]='\0';
        printf("Picture being displayed:%s\n",file_name);
        //Start a new process
        execlp("eog","eog",file_name,NULL);
    }
    else  //Parent process
    {
        //Determine whether it is a picture
        if(strstr(dir_info->d_name,".jpg"))
        {
            char *p;
            //Path of combined pictures
            p=malloc(strlen(argv[1])+strlen(dir_info->d_name)+1);
            sprintf(p,"%s%s",argv[1],dir_info->d_name);
            //Write data to the write end of the pipe
            write(fds[1],p,strlen(p)); 
            //Delay 2 seconds
            sleep(2);
            //Kill all child processes created by the parent process
            char cmd_buff[100];
            sprintf(cmd_buff,"pkill -9 -P %d",getpid());
            system(cmd_buff);
            //Clean up space for child processes
            wait(NULL);
        } 
        //Continue to display the next picture
         goto AA;
    }

    return 0;
}

Keywords: Linux Operation & Maintenance server

Added by adamjblakey on Thu, 27 Jan 2022 22:24:43 +0200