《Linux/UNIX系统编程手册》 英文版读书笔记第28章 2014.11.20


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



The principal advantages ofsystem()are simplicity and convenience:
z We don’t need to handle the details of calling fork(), exec(), wait(), and exit().
z Error and signal handling are performed by system() on our behalf.
z Because system()uses the shell to executecommand, all of the usual shell processing, substitutions, and redirections are performed oncommandbefore it is 
executed. This makes it easy to add an “execute a shell command” feature to an

application. (Many interactive applications provide such a feature in the form of a!command.)



This has two undesirable consequences:
z The calling program would be deceived into thinking that one of the children
that it created has terminated.
z The system() function would be unable to obtain the termination status of the child that it created.
Therefore, system() must block delivery ofSIGCHLDwhile it is executing.


The other signals to consider are those generated by the terminal interrupt
(usually Control-C) and quit (usually Control-\) characters,SIGINTand SIGQUIT, respectively. Consider what is happening when we execute the following call:

system("sleep 20");

At this point, three processes are running

The shell ignoresSIGINTand SIGQUIT while waiting for its child. 

 SUSv3 specifies the following:
z SIGINT and SIGQUIT should be ignored in the calling process while the command is being executed.
z In the child, SIGINT and SIGQUIT should be treated as they would be if the calling process did afork()and exec(); that is, the disposition of handled signals is reset to the default, and the disposition of other signals remains unchanged.

While the command is being executed, typingControl-Cor Control-\  will kill only the child ofsystem(), while the application (unexpectedly, to the user) continues to run

A program that usessystem()in this way should check the termination status returned bysystem(), and take appropriate action if it detects that the command was killed by a signal.

The:command is a shell built-in command that does nothing, but always returns a success status

It is only in the parent process (the caller ofsystem()) thatSIGCHLDneeds to be blocked, andSIGINT and SIGQUIT need to be ignored

In the parent, we ignore errors from thesigaction()and sigprocmask()calls used to manipulate signal dispositions and the signal mask 

we assume that the caller is more interested in knowing iffork()or waitpid()failed than in knowing if these signal-manipulation calls failed. For similar reasons, we bracket the signal-manipulation calls used at the end of system()with code to savei and restore errno。

the use of _exit(127)is reserved for reporting an error when execing the shell

Error checking is not performed for signal-related system calls in the child ,such failures don’t affect the caller of system(), which is a separate process.

On return from fork() in the child, the disposition ofSIGINTand SIGQUIT is SIG_IGN(i.e., the disposition inherited from the parent)


in the child, these signals should be treated as if the caller ofsystem()did a fork() and anexec(). Afork()leaves the treatment of signals unchanged in the child.
An exec() resets the dispositions of handled signals to their defaults and leaves the dispositions of other signals unchanged

If theexecl()call in the child fails, then we use_exit() to terminate the processrather thanexit(), in order to prevent flushing of any unwritten data in the child’s copy of thestdiobuffers.

In the parent, we must usewaitpid()to wait specifically for the child that we created

the calling program may have established signal handlers, and one of  these could interrupt a blocked call to waitpid(). SUSv3 explicitly requires that  the wait be restarted in this case. Therefore, we use a loop to restart waitpid()if  it fails with the error EINTR; any other error fromwaitpid()causes this loop to  terminate.



下载地址请见:







你可能感兴趣的:(《Linux/UNIX系统编程手册》 英文版读书笔记第28章 2014.11.20)