/DUP function: copy an existing handle to generate a new handle that is exactly the same as the "source handle feature" (that is, generate a new handle number, and associated with the same device)
// Functions of the dup2 function: copy an existing handle to another handle. The target handle features exactly the same as that of the source handle feature (that is, first close the target handle, disconnect from the device, and then completely copy from the source handle to the target handle)
// DUP and dup2 are both system services. The window platform corresponds to the duplicatehandle function.
/* DUP.C: This program uses the variable old to save * the original stdout. It then opens a new file named * new and forces stdout to refer to it. Finally, it * restores stdout to its original state. */#i nclude <io.h>#i nclude <stdlib.h>#i nclude <stdio.h>void main( void ){ int old; FILE *new; old = _dup( 1 ); /* "old" now refers to "stdout" */ /* Note: file handle 1 == "stdout" */ if( old == -1 ) { perror( "_dup( 1 ) failure" ); exit( 1 ); } write( old, "This goes to stdout first/r/n", 27 ); if( ( new = fopen( "data", "w" ) ) == NULL ) { puts( "Can't open file 'data'/n" ); exit( 1 ); } /* stdout now refers to file "data" */ if( -1 == _dup2( _fileno( new ), 1 ) ) { perror( "Can't _dup2 stdout" ); exit( 1 ); } puts( "This goes to file 'data'/r/n" ); /* Flush stdout stream buffer so it goes to correct file */ fflush( stdout ); fclose( new ); /* Restore original stdout */ _dup2( old, 1 ); puts( "This goes to stdout/n" ); puts( "The file 'data' contains:" ); system( "type data" );}
Output
This goes to stdout firstThis goes to file 'data'This goes to stdoutThe file 'data' contains:This goes to file 'data'
About fcntl (FD, f_setfd, fd_cloexec) setting the close attribute during Exec
Snd_ctl_hw_open
# Define sndrv_file_control alsa_device_directory "controlc % I"
Sprintf (filename, sndrv_file_control, card); // path/dev/snd/controlc0
FD = snd_open_device (filename, fmode );
Fcntl (FD, f_setfd, fd_cloexec); // The value fd_cloexec indicates that this FD will be automatically disabled when the program executes the exec function, indicating that it will not be passed to the new process created by Exec, if it is set to fcntl (FD, f_setfd, 0), This FD will remain open and copied to the new thread created by Exec [Luther. gliethttp].
Go to kernel system call
Sys_fcntl
Do_fcntl
Case f_setfd:
Err = 0;
Set_close_on_exec (FD, Arg & fd_cloexec );
Void fastcall set_close_on_exec (unsigned int FD, int flag)
{
Struct files_struct * files = Current-> files;
Struct fdtable * FDT;
Spin_lock (& files-> file_lock );
FDT = files_fdtable (files );
If (FLAG)
Fd_set (FD, FDT-> close_on_exec );
Else
Fd_clr (FD, FDT-> close_on_exec );
Spin_unlock (& files-> file_lock );
}
The following is the description of fd_cloexec seen by man fcntl.
File descriptor flags
The following commands manipulate the flags associated with a file descriptor. Currently, only one such flag is
Defined: fd_cloexec, the close-on-exec flag. If the fd_cloexec bit is 0, the file descriptor will remain open
Stored SS an execve (2), otherwise it will be closed.
F_getfd (void)
Read the file descriptor flags; Arg is ignored.
F_setfd (long)
Set the file descriptor flags to the value specified by Arg.
Int cwatchdogdaemon: fork (void)
{
// An error detection Pipe
Int err, FD [2];
Pipe (FD );
// Fork child process
PID = fork ();
If (pid =-1)
Return PID;
If (pid = 0)
{
// Close pipe if exec succ
Close (FD [0]);
Fcntl (FD [1], f_setfd, fd_cloexec );
Exec ();
Err = errno;
Log_error ("% s: exec (): % m", name );
Write (FD [1], & err, sizeof (ERR ));
Exit (-1 );
}
Close (FD [1]);
If (read (FD [0], & err, sizeof (ERR) = sizeof (ERR ))
{
Errno = err;
Return-1;
}
Close (FD [0]);
Attachwatchdog ();
Return PID;
}
At first glance, I thought there was a problem. I felt that the parent process would read a byte no matter how it was due to read blocking reading and writing, causing the parent process to exit.
Finally, we found that the following line of code is working:
Fcntl (FD [1], f_setfd, fd_cloexec );
Setting this flag will cause the process to close the pipeline if it successfully calls the exec interface, and write a byte ending flag to the management when closing the pipeline. In this way, read will return 1, causing the condition to be invalid. Otherwise, if the parent process of the pipeline is not closed, the message indicating that the sub-process failed to be executed will be displayed correctly.