Linux System Programming 34 Process Control-Fork() Detailed Explanation 1. The connection with line buffer and full buffer must be refreshed by fflush()

1 getpid()/getppid
2 fork()


getpid()/getppid

NAME
getpid, getppid - get process identification

SYNOPSIS
#include <sys/types.h>
#include <unistd.h>

   pid_t getpid(void);
   pid_t getppid(void);

DESCRIPTION
getpid() returns the process ID of the calling process. (This is often used by routines that generate unique temporary filenames.)

getppid() returns the process ID of the parent of the calling process.


fork()

NAME
fork - create a child process

SYNOPSIS
#include <unistd.h>

   pid_t fork(void);

DESCRIPTION
fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.

Create a new process by copying the current process, that is, the parent and child processes are the same, and the execution location is also the same

RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

Explanation: After
fork(), the pid of the child process is returned in the parent process, and the return value is 0 in the child process. At this time, the code becomes two copies, two copies of the same code, even the execution position is the same.

Insert picture description here

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

int main(void)
{

	pid_t pid;

	printf("[%d]:Begin!\n",getpid());

	pid = fork();
	if(pid < 0)
	{
		fprintf(stderr,"getpid() failed!");
		exit(1);
	}

	//child
	if(pid == 0)
	{
		printf("[%d]:Chiled is working\n",getpid());
	}
	else//parrent
	{
		printf("[%d]:Parrent is working\n",getpid());
	}

	printf("[%d]:End!\n",getpid());
	exit(0);

}



mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
[13186]:Begin!
[13186]:Parrent is working
[13186]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ [13187]:Chiled is working
[13187]:End!
^C
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

Note:
Pay attention to the results of the program:

[13186]:Begin!
[13186]:Parrent is working
[13186]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ [13187]:Chiled is working
[13187]:End!

That is, the
first part: print Begin. The
second part: end after the parent process statement is executed. The
third part: end after the child process statement is executed.

Question 1 The
first thing to pay attention to is the execution order of the parent and child processes. The execution order of the parent and child processes is determined by the program scheduler. It is not determined by us. It may be that the content of the child process is executed first, and then the content of the parent process.

Question 2
Secondly, about printing Begin, why is it only printed once?

Regarding question 1:
If the child process must run first, you can sleep() in the parent process statement:

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

int main(void)
{

	pid_t pid;

	printf("[%d]:Begin!\n",getpid());

	pid = fork();
	if(pid < 0)
	{
		fprintf(stderr,"getpid() failed!");
		exit(1);
	}

	//child
	if(pid == 0)
	{
		printf("[%d]:Chiled is working\n",getpid());
	}
	else//parrent
	{
		sleep(1);
		printf("[%d]:Parrent is working\n",getpid());
	}

	printf("[%d]:End!\n",getpid());
	exit(0);

}

mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
[13255]:Begin!
[13256]:Chiled is working
[13256]:End!
[13255]:Parrent is working
[13255]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

Regarding question 2: There is a line break and printed to the line buffer terminal
as follows:

printf("[%d]:Begin!\n",getpid());

If the standard output is a terminal device, the standard output is line buffered, otherwise it is fully buffered

The reason why Begin is only printed once on the terminal is that the terminal is in line buffer mode. Due to the newline character that follows, the contents of the buffer have been flushed to the disk, and the buffer has been emptied. Therefore, Begin will be printed in the parent process, but there is no Begin information in the buffer copied from the child process. It has already been refreshed in the parent process, so Begin will not be printed again in the child process.

Variation 1: The standard output is the terminal line buffer with line breaks removed

printf("[%d]:Begin!",getpid()); 

result:

mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
[14003]:Begin![14003]:Parrent is working
[14003]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ [14003]:Begin![14004]:Chiled is working
[14004]:End!

Print Begin twice. At this time, Begin will be printed once in the parent process and the child process. Similarly, the terminal is standard output, and the newline character is refreshed. At this time, there is no newline character. The Begin information of the parent process is stored in the buffer before exit. , And did not write to the disk. Similarly, the buffer of the copied child process also has Begin information. So the two processes will print Begin twice when they exit

Variation 2: Redirect to a file in full buffer mode

mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out > TEST_FILE 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ cat TEST_FILE 
[14084]:Begin![14084]:Parrent is working
[14084]:End!
[14084]:Begin![14085]:Chiled is working
[14085]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

When redirecting standard output to a file, the standard output is in full buffer mode, that is, the buffer will not be refreshed regardless of whether there is a newline character, that is, it will not be written to disk, which is the buffer of two processes. Each area has Begin information, so it will be printed twice.

Important: fflush all open streams before fork() to avoid repeated printing by the child process

Therefore, for the above reasons, we generally fflush() once before fork() to refresh all successfully opened streams:

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

int main(void)
{

	pid_t pid;

	printf("[%d]:Begin!\n",getpid());
	
	fflush(NULL);

	pid = fork();
	if(pid < 0)
	{
		fprintf(stderr,"getpid() failed!");
		exit(1);
	}

	//child
	if(pid == 0)
	{
		printf("[%d]:Chiled is working\n",getpid());
	}
	else//parrent
	{
		//sleep(1);
		printf("[%d]:Parrent is working\n",getpid());
	}

	printf("[%d]:End!\n",getpid());
	exit(0);

}


mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ gcc test.c 

mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ ./a.out 
[14169]:Begin!
[14169]:Parrent is working
[14169]:End!
mhr@ubuntu:~/Desktop/xitongbiancheng/test$ [14170]:Chiled is working
[14170]:End!

mhr@ubuntu:~/Desktop/xitongbiancheng/test$ 

Guess you like

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