Can the child process copy the buffer of the parent process?

In the process control section of "UNIX Advanced Environment Programming", there is an example that is almost like this:
change variables in the child process and observe the changes in the variables after the parent process

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include<sys/mman.h>
#include<pthread.h>
#include<semaphore.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<sys/epoll.h>
#include<unistd.h>
#include<dirent.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<errno.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/wait.h>
int glob=6;
char buf[]="write to stdout\n";
int main(int argc,char**argv)
{
    
    
    int var;
    pid_t pid;
    var =88;
    if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1){
    
    
        fprintf(stderr,"write error");
        exit(0);
    }
    printf("before fork\n");
    // fflush(stdout);
    // setbuf(stdout,NULL);
    // setvbuf(stdout,(char*)NULL,_IONBF,0);
    if((pid=fork())<0){
    
    
        fprintf(stderr,"fork error");
        exit(0);
    }else if(pid==0){
    
    
        glob++;
        var++;
    }else
        sleep(2);
    printf("pid =%d ,glob =%d ,var=%d\n",getpid(),glob,var);
    return 0;
}

At the beginning, I also thought it was the case, because the child process copies the parent process's stack and data space when writing, and the child process changes the variables of the parent process.
But the book suddenly turned around and mentioned the problem of copying the standard IO function write buffer.

The problem is this: our write (STDOUT_FILENO) is printed once in the terminal, and our printf ("before fork\n") is printed once in the terminal. But if we redirect this result into a file in a.out >a.txtthe form of
redirection, will these statements be printed several times???
Answer: write(STDOUT_FILENO) is printed once, and printf("before fork\n") is printed twice
. What happened? ? ? The book pointed out that write does not have a cache, and printf has a 8192-byte cache. What is surprising and easy to be overlooked is that the child process will inherit the contents of the parent process's write buffer . So why did it not print this sentence when I wrote it to the terminal, but it appeared when I wrote it to the file?
This is because the standard output is the line buffer. There is a newline character of'\n' in the content that we wrote to refresh the line buffer. The process therefore cannot get this content; however, the redirection is to make the output point to the file, and at this time its buffering mode becomes the buffering mode for writing ordinary files: full buffering (do not understand Chapter 5 of "UNIX Advanced Environment Programming") This leads to the content of the buffer in the buffer after the printf of our parent process is finished, and the content is copied to the child process, the child process will also print this sentence.

Curious babies will ask, how can the child process not print this sentence? ? ?
The answer is to use one of these three functions to refresh the buffer after the parent process printf.

     fflush(stdout);
     setbuf(stdout,NULL);
    setvbuf(stdout,(char*)NULL,_IONBF,0);

You can also notice that the write buffer is 8192 bytes. If we write more than 8192 bytes, has the buffer been flushed?
The answer is yes.

The following experiment: I add a lot of spaces in printf ("before fork\n") until the string has 300 bytes. Then we print it 30 times, 3000×30=9000=8192; this means that under this full buffer, we have all the contents of the buffer flushed out after printing 300×28=8400 bytes. Can we print sentence strings in the file? ? ? The 30+ of the parent process is still inherited to the child process in the buffer (30-28)=32. The answer is indeed so.

At this time, we use this command to a.out |grep before | wc
guess the number of rows we can see? That's 32! Here |it is also redirect the standard output to the executable file in grep. If you haven't read this article before, you must have thought it would be 30! ! ! Surprised?

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include<sys/mman.h>
#include<pthread.h>
#include<semaphore.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<sys/epoll.h>
#include<unistd.h>
#include<dirent.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<errno.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/wait.h>
int glob=6;
char buf[]="write to stdout\n";
int main(int argc,char**argv)
{
    
    
    int var;
    pid_t pid;
    var =88;
    if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1){
    
    
        fprintf(stderr,"write error");
        exit(0);
    }
for(int i=0;i<30;i++)
    printf("before fork                                                                                                                                                                                                                                                                                               \n");

    // fflush(stdout);
    // setbuf(stdout,NULL);
    // setvbuf(stdout,(char*)NULL,_IONBF,0);
    if((pid=fork())<0){
    
    
        fprintf(stderr,"fork error");
        exit(0);
    }else if(pid==0){
    
    
        glob++;
        var++;
    }else
        sleep(2);
    printf("pid =%d ,glob =%d ,var=%d\n",getpid(),glob,var);
    return 0;
}

Discovered it, you can gain a lot by doing small experiments yourself.

Guess you like

Origin blog.csdn.net/adlatereturn/article/details/105691795