12th Chapter Line Program Control system
On the thinking of exercise 12.1
</pre><pre name= "code" class= "CPP" > #include "apue.h" #include <pthread.h> pthread_mutex_t lock1 =
Pthread_mutex_initializer;
pthread_mutex_t Lock2 = Pthread_mutex_initializer;
void Prepare () {printf ("Preparing locks....%d \ n", Getpid ());
Pthread_mutex_lock (&LOCK1);
Pthread_mutex_lock (&LOCK2);
} void Parent () {printf ("Parent unlocking locks.%d \ n", Getpid ());
Pthread_mutex_unlock (&LOCK1);
Pthread_mutex_unlock (&LOCK2); } void Child () {printf ("Child unlcoking locks.
%d\n ", Getpid ());
Pthread_mutex_unlock (&LOCK1);
Pthread_mutex_unlock (&LOCK2);
} void * THR_FN (void *arg) {printf ("This is a new thread%d \ n", Getpid ());
Pause ();
return (0);
} int main () {pid_t pid;
pthread_t Tid;
Pthread_atfork (Prepare, parent, child);
Pthread_create (&tid, NULL, THR_FN, NULL);
Sleep (2); printf ("Parent fork".
%d\n ", Getpid ());
if (PID = fork ()) < 0) {return-1; } else if (PID = = 0) {printf ("Child return from Fork%d\n", Getpid ());
} else {printf ("Parent Return from fork%d\n", Getpid ());
} return 0; }
Compile and execute two times, direct data once, redirect to file at once via pipeline
[advancedprograminginunixenviroment]$./1217 This is
a new thread 31855
parent Fork: 31855
Preparing locks .... 31855
Parent Unlocking locks.31855
parent return from fork 31855 child
unlcoking locks. 31868
Return from fork 31868
[advancedprograminginunixenviroment]$ rm file
[advancedprograminginunixenviroment]$. /1217 > File
[advancedprograminginunixenviroment]$ cat file This is
a new thread 32051
parent Fork: 32051
Preparing locks .... 32051
Parent Unlocking locks.32051
parent return from Fork 32051 The is
a new thread 32051 the
parent for K.. 32051
Preparing locks .... 32051 child
unlcoking locks. 32068 Child
return from fork 32068
As you can see, the output results are different after the file redirection
Guess, when you redirect the output of the file, after fork, the equivalent of the parent process and the child process two processes, the output will be executed once, and successively redirected to the file.
In the ordinary case, it is output directly in a stream.
For easy analysis, replace the above program with a simple applet
#include "apue.h"
#include <pthread.h>
int main ()
{
pid_t pid;
printf ("Prepare fork%d\n", Getpid ());
if (PID = fork ()) < 0) {
return-1;
} else if (PID = = 0) {
printf ("This is a child%d\n", Getpid ());
Sleep (+);
} else {
printf ("This is parent%d\n", Getpid ());
Sleep (+);
/*pid = fork ();
if (PID = = 0) {
printf ("This was another child%d\n", Getpid ());
} else {
printf ("the" this was always the parent%d \ n ", Getpid ());
} */
}
return 0;
}
With the Linux strace command, you can track the execution of a command, understand its details, and analyze it through the command. It can be found that the Wirte command is not the same, the former is each write once to FD 1 is the standard output, the latter only write once.
First time
Fstat (1, {st_mode=s_ifchr|0620, St_rdev=makedev (136, 6), ...}) = 0
mmap (NULL, 4096, prot_read| Prot_write, map_private| Map_anonymous,-1, 0) = 0x7f09d29cc000
Write (1, "Prepare fork 61180\n", 19prepare fork 61180
) =
Clone (Child_stack=0, flags=clone_child_cleartid| clone_child_settid| SIGCHLD, child_tidptr=0x7f09d29b3770) = 61181
Write (1, "This is the parent 61180\n", 21this is the parent 61180
) = 21 This
is the child 61181 clone (Child_stack=0, flags=clone_child_cleartid| clone_child_settid| SIGCHLD, child_tidptr=0x7f09d29b3770) = 61182
Write (1, "This was always the parent 61180\n", 28this is another child 61182 This is always
parent 61180
) =
Munmap (0x7f09d29cc000, 4096) = 0
Second time
Fstat (1, {st_mode=s_ifreg|0664, st_size=0, ...}) = 0
mmap (NULL, 4096, prot_read| Prot_write, map_private| Map_anonymous,-1, 0) = 0x7f3dfd604000
Clone (child_stack=0, flags=clone_child_cleartid| clone_child_settid| SIGCHLD, child_tidptr=0x7f3dfd5eb770) = 1525
Clone (child_stack=0, flags=clone_child_cleartid| clone_child_settid| SIGCHLD, child_tidptr=0x7f3dfd5eb770) = 1526
Write (1, "Prepare fork 1524\nthis is parent" ..., 65) = 65
The next look at two executions, the output stream for each thread, is the first of the following
[advancedprograminginunixenviroment]$./forktest & [1] 22334 [advancedprograminginunixenviroment]$ Prepare fork 22334 This is the parent 22334 this was child 22335 [advancedprograminginunixenviroment]$ [lijingyi01@cp01-rdqa-dev401.cp01.b aidu.com advancedprograminginunixenviroment]$ Ps-ef | grep Fork 1026 22334 54923 0 17:44 pts/6 00:00:00./forktest 1026 22335 22334 0 17:44 pts/6 00:00:00./for Ktest 1026 22521 54923 0 17:44 pts/6 00:00:00 grep Fork [advancedprograminginunixenviroment]$ ll/proc/22334/fd to Tal 0 lrwx------1 lijingyi01 lijingyi01 Oct 17:44 0/DEV/PTS/6 lrwx------1 lijingyi01 lijingyi01 Oct 21 17:44 1,/DEV/PTS/6 lrwx------1 lijingyi01 lijingyi01 Oct 17:44 2,/DEV/PTS/6 [Advancedprograminginunix enviroment]$ ll/proc/22335/fd Total 0 lrwx------1 lijingyi01 lijingyi01 Oct 17:45 0/DEV/PTS/6 lrwx------ 1 lijingyi01 lijingyi01 Oct 17:45 1/DEV/PTS/6 lrwx------1 lijingyi01 lijingyi01 64 OCT 17:44 2-/DEV/PTS/6
Second time
[advancedprograminginunixenviroment]$/forktest > File4 & [1] 36359 [advancedprograminginunixenviroment]$ PS- EF | grep Fork 1026 36359 54923 0 17:48 pts/6 00:00:00./forktest 1026 36360 36359 0 17:48 pts/6 00:00:00./for Ktest 1026 36385 54923 0 17:48 pts/6 00:00:00 grep Fork [advancedprograminginunixenviroment]$ ll/proc/36360/fd to Tal 0 lrwx------1 lijingyi01 lijingyi01 Oct 17:48 0/DEV/PTS/6 l-wx------1 lijingyi01 lijingyi01 Oct 21 17:48 1,/home/users/lijingyi01/work/advancedprograminginunixenviroment/file4 lrwx------1 lijingyi01 lijingyi01 OCT 17:48 2-/DEV/PTS/6 [advancedprograminginunixenviroment]$ ll/proc/36359/fd total 0 lrwx------1 lijingyi0 1 lijingyi01 Oct 17:48 0-/DEV/PTS/6 l-wx------1 lijingyi01 lijingyi01 Oct 17:48 1-/home/users/li Jingyi01/work/advancedprograminginunixenviroment/file4 lrwx------1 lijingyi01 lijingyi01 Oct 17:48 2-/dev/pt S/6
As you can see, when you redirect to a file, both the main process and the child process are assigned to the corresponding file, then all output from a single process is started to be cached in a buff and then printed to the file once.
But the weird thing is,
Write (1, "Prepare fork 1524\nthis is parent" ..., 65) = 65
The character that is written to the file is a length of 65, which is exactly the length of the three line, not the four line.
In the program to change printf to C + + cout after the Endl emptied the stream, after the file redirection data after the result is the same as the original, so now the clear conclusion is that the output to the shell is a buffer, two processes shared, output after the refresh. While redirecting to the file, the main process has started to put the first sentence into the output buffer, when the fork, the buffer is also the quilt process replication, so the child process also has the first sentence, and then the main process and the child process all the data to the respective buffer, and then output to the file respectively.