Linux System Programming 38 Process Control-exec function family must add fflush, with fork+execl+wait

Experiment 1: execl is used, fflush() must be added to refresh the stream.
Experiment 2: fork() execl() wait() combined use

few:fork + exec + wait

Introduction:
Run the following program and execute the ps axf command to view the following parent-child process relationship:

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

#define LEFT 200
#define RIGHT 250

int main(void)
{
	int i,j,mark;
	pid_t pid;
	
	for(i = LEFT; i <= RIGHT; i++)
	{
		pid = fork();
		if(pid < 0)
		{
			fprintf(stderr,"fork() failed!\n");
			exit(1);
		}
		else if(pid == 0)//child
		{
			mark = 1;
			for(j = 2; j < i/2; j++)
			{
				if(i % j ==0)
					{
						mark = 0;
						break;
					}
			
			}

			if(mark)
				printf("%d is a primer\n",i);

			exit(0);//!!!
		}
		
	}

	sleep(1000);
	exit(0);
}


  2837 pts/0    Ss     0:01          |   \_ /bin/bash
 26731 pts/0    S+     0:00          |   |   \_ ./a.out
 26732 pts/0    Z+     0:00          |   |       \_ [a.out] <defunct>
 26733 pts/0    Z+     0:00          |   |       \_ [a.out] <defunct>
 26734 pts/0    Z+     0:00          |   |       \_ [a.out] <defunct>
 26735 pts/0    Z+     0:00          |   |       \_ [a.out] <defunct>
....

You can see that the
shell process is the parent process of the
a.out process a.out parent process is the parent process of the remaining 201 a.out processes

Question 1: About the relationship between the shell process and the a.out process

So here comes the problem. The relationship between a.out and the 201 a.outs he forks is easy to understand. But how to understand the relationship between the shell process and the parent process of a.out?
We learned earlier that the relationship between the parent process and the child process is to get the child process by copying the parent process itself. After fork(), the code and execution position of the child process and the parent process are exactly the same, except that the parent and child processes go down When it is executed, it will select the pre-set code that needs to be executed according to its own identity. So why is the shell process different from the a.out process? It stands to reason that the child process of the shell process should also be the shell process. Now a.out is obviously different from the shell. How should we understand it here?


exec function family:

NAME
execl, execlp, execle, execv, execvp, execvpe-execute a file execute a file! ! !

SYNOPSIS
   #include <unistd.h>

   extern char **environ;

   int execl(const char *path, const char *arg, ...
                   /* (char  *) NULL */);
   int execlp(const char *file, const char *arg, ...
                   /* (char  *) NULL */);
   int execle(const char *path, const char *arg, ...
                   /*, (char *) NULL, char * const envp[] */);
   int execv(const char *path, char *const argv[]);
   int execvp(const char *file, char *const argv[]);
   int execvpe(const char *file, char *const argv[],
                   char *const envp[]);

The exec() family of functions replaces the current process image with a new process image.

The exec function family replaces the current process image with a new process image. It
Insert picture description here
does not create a new process, but only replaces a process.

RETURN VALUE
The exec() functions return only if an error has occurred. The return value is -1, and errno is set to indicate the error.

exec only returns a value when the execution fails.


Experiment 1: First experience of exec, the connection between exec and buffer must pay attention to fflush()

Command: date +%s: Get the current time in the specified format

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


int main(void)
{
	int i,j,mark,n;
	pid_t pid;
	
	puts("Begin!");//puts() 输出时会自动换行

	execl("/bin/date","date","+%s",NULL);
	perror("execl");//如果执行到此 说明 exec替换失败
	exit(1);

	puts("End!\n");
		
	
	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
Begin!
1613136072
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out > /tmp/out
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ cat /tmp/out
1613136191
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

The result is as expected, when the program is executed to exec(), the current process is replaced with the date process

Note: When executing an executable program on the command line, Begin is printed, but after relocation to /tmp/out, Begin will not be printed.

why???

When the command line is executed, puts is output to the terminal, that is, standard output, which is line buffer, so there is Begin printing. When relocated to /tmp/out, puts is output to a fully buffered file. The newline character does not refresh the buffer, but is stored in the buffer, and executes execl() before refreshing, that is, the date process image is replaced. The current process image and buffer information are also overwritten. So we must pay attention to:

fflush(NULL) before fork() and fflush(NULL
) before execl() to
flush the buffer! ! !

which is:

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


int main(void)
{
	int i,j,mark,n;
	pid_t pid;
	
	puts("Begin!");//puts() 输出时会自动换行
fflush(NULL);
	execl("/bin/date","date","+%s",NULL);
	perror("execl");//如果执行到此 说明 exec替换失败
	exit(1);

	puts("End!\n");
		
	
	exit(0);
}



mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out > /tmp/out
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ cat /tmp/out
Begin!
1613136824
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

In Experiment 1, it doesn't make any sense to use a new process image to replace the current process image written by myself. It is better to use the new process directly, so where is the main application of exec? ?

Experiment 2: The meaning of exec, fork() exec() wait() Three axes use: overwhelming

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


int main(void)
{
	int i,j,mark,n;
	pid_t pid;
	
	puts("Begin!");

	fflush(NULL);
	pid = fork();
	if(pid < 0)
	{
		perror("fork()");
		exit(1);
	}
	else if(pid == 0) //child  用子进程替换 date
	{
		fflush(NULL);
		execl("/bin/date","date","+%s",NULL);
		perror("execl");
		exit(1);
	}

	wait(NULL);

	puts("End!");
		
	
	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
Begin!
1613137594
End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out > /tmp/out
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ cat /tmp/out
Begin!
1613137607
End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

The parent process is responsible for creating the child process. The child process is responsible for work, that is, replaced by the date process, and finally the parent process is waiting to release the child process resources.

So here is the explanation of question 1
about the relationship between the shell process and the a.out process. Obviously a child process image in the shell process has been replaced with the a.out process image! ! !

Guess you like

Origin blog.csdn.net/LinuxArmbiggod/article/details/113797632