pipe、dup、dup2、wait、waitpid、fork函数说明
pipe、dup、dup2、wait、waitpid、fork函数说明
int pipe( int fd[ 2 ]);
功能:创建一个简单的管道,若成功则为数组fd分配两个文件描述符,其中fd[ 0 ] 用于读取管道,fd[ 1 ]用于写入管道。
返回:成功返回0,失败返回 - 1 ;
管道是Linux 支持的最初Unix IPC形式之一,具有以下特点:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系 统,并且只存在与内存中。 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
但值得我们注意的是:管道它有自身的特点。
( 1 )管道通信是单向的,并且遵守先进先出的原则,即先写入的数据先读出。
( 2 )管道是一个无结构,无固定大小的字节流。
( 3 )两个返回的文件描述符以一种特殊的方式连接起来.写到fd[ 1 ]的数据都可以从fd[ 0 ]中读回来.
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
int dup( int fd)
复制一个存在的文件描述符,返回当前可用的最小文件描述符。。。比如当前文件描述符已经到了100,使用 dup( 100 ) ,将返回 101 ,101这个文件描述符拥有100的所有东西,复制了嘛。。。
int dup2( int fd, int fd2)
是可以指定一个文件描述符(fd2)来使用,如果fd2已经打开,则会先将其关闭,如果 fd == fd2 ,直接返回 fd2 且不关闭。
实际上 fcntl 也能完成这2个函数的功能,只是对于 dup2 来说,fcntl 是调用2个函数,而 dup2 是一个原子操作。
dup函数的作用:复制一个现有的句柄,产生一个与“源句柄特性”完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备)
dup2函数的作用:复制一个现有的句柄到另一个句柄上,目标句柄的特性与“源句柄特性”完全一样(也即首先关闭目标句柄,与设备断连,接着从源句柄完全拷贝复制到目标句柄)
wait和waitpid函数
头文件
#include < sys / types.h >
#include < sys / wait.h >
函数 pid_t wait ( int * status);
进程一旦调用了 wait,就 立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息, 并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
wait(等待子进程中断或结束)
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 - 1 。失败原因存于errno 中。
waitpid(等待子进程中断或结束)
相关函数 wait,fork
表头文件
#include < sys / types.h >
#include < sys / wait.h >
定义函数 pid_t waitpid(pid_t pid, int * status, int options);
函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。
参数pid 为欲等待的子进程识别码,其他数值意义如下:
pid <- 1 等待进程组识别码为pid 绝对值的任何子进程。
pid =- 1 等待任何子进程,相当于wait()。
pid = 0 等待进程组识别码与目前进程相同的任何子进程。
pid > 0 等待任何子进程识别码为pid 的子进程。
目前在Linux中只支持WNOHANG和WUNTRACED两个选项,
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
如果我们不想使用它们,也可以把options设为0,如:
ret = waitpid( - 1 ,NULL, 0 );
如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。
而WUNTRACED参数,用于跟踪调试,极少用到,就不说了。
查看linux源代码 unistd.h 我们会发现,其实 wait 就是经过包装的 waitpid:
static inline pid_t wait( int * wait_stat)
{
return waitpid( - 1 ,wait_stat, 0 );
}
可以用kill函数杀死子进程
kill(childPid,SIGKILL);
子进程的结束状态返回后存于status,下面有几个宏可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
if (WIFEXITED(status))
{
printf( " exited, status=%d/n " , WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
printf( " killed by signal %d/n " , WTERMSIG(status));
}
else if (WIFSTOPPED(status)) {
printf( " stopped by signal %d/n " , WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) {
printf( " continued/n " );
}
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 - 1 。失败原因存于errno 中。
fork函数
Create a new process
程序段里用了fork();之后程序出了分岔,派生出了两个进程。具体哪个先运行就看该操作的系统的调度算法了。
函数返回2次.
返回值得在子进程中pid的值为0,通过getpid可以获取子进程的进程id;
返回值:
A value of zero to the child process; and the process ID of the child process to the parent process.
Both processes continue to execute from the fork() function. If an error occurs, fork() returns - 1 to the parent and sets errno.
#include < sys / types.h >
#include < process.h >
int main()
{
pid_t pid;
puts( " <1> " );
pid = fork();
if (pid < 0 ) {
printf( " error in fork! \r\n " );
}
else if (pid == 0 ) {
printf( " i am the child process, my process id is %d \r\n " ,getpid());
}
else {
printf( " i am the parent process, my process id is %d \r\n " ,getpid());
}
puts( " <2> " );
return 0 ;
}
int pipe( int fd[ 2 ]);
功能:创建一个简单的管道,若成功则为数组fd分配两个文件描述符,其中fd[ 0 ] 用于读取管道,fd[ 1 ]用于写入管道。
返回:成功返回0,失败返回 - 1 ;
管道是Linux 支持的最初Unix IPC形式之一,具有以下特点:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系 统,并且只存在与内存中。 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
但值得我们注意的是:管道它有自身的特点。
( 1 )管道通信是单向的,并且遵守先进先出的原则,即先写入的数据先读出。
( 2 )管道是一个无结构,无固定大小的字节流。
( 3 )两个返回的文件描述符以一种特殊的方式连接起来.写到fd[ 1 ]的数据都可以从fd[ 0 ]中读回来.
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
int dup( int fd)
复制一个存在的文件描述符,返回当前可用的最小文件描述符。。。比如当前文件描述符已经到了100,使用 dup( 100 ) ,将返回 101 ,101这个文件描述符拥有100的所有东西,复制了嘛。。。
int dup2( int fd, int fd2)
是可以指定一个文件描述符(fd2)来使用,如果fd2已经打开,则会先将其关闭,如果 fd == fd2 ,直接返回 fd2 且不关闭。
实际上 fcntl 也能完成这2个函数的功能,只是对于 dup2 来说,fcntl 是调用2个函数,而 dup2 是一个原子操作。
dup函数的作用:复制一个现有的句柄,产生一个与“源句柄特性”完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备)
dup2函数的作用:复制一个现有的句柄到另一个句柄上,目标句柄的特性与“源句柄特性”完全一样(也即首先关闭目标句柄,与设备断连,接着从源句柄完全拷贝复制到目标句柄)
wait和waitpid函数
头文件
#include < sys / types.h >
#include < sys / wait.h >
函数 pid_t wait ( int * status);
进程一旦调用了 wait,就 立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息, 并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
wait(等待子进程中断或结束)
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 - 1 。失败原因存于errno 中。
waitpid(等待子进程中断或结束)
相关函数 wait,fork
表头文件
#include < sys / types.h >
#include < sys / wait.h >
定义函数 pid_t waitpid(pid_t pid, int * status, int options);
函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。
参数pid 为欲等待的子进程识别码,其他数值意义如下:
pid <- 1 等待进程组识别码为pid 绝对值的任何子进程。
pid =- 1 等待任何子进程,相当于wait()。
pid = 0 等待进程组识别码与目前进程相同的任何子进程。
pid > 0 等待任何子进程识别码为pid 的子进程。
目前在Linux中只支持WNOHANG和WUNTRACED两个选项,
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
如果我们不想使用它们,也可以把options设为0,如:
ret = waitpid( - 1 ,NULL, 0 );
如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。
而WUNTRACED参数,用于跟踪调试,极少用到,就不说了。
查看linux源代码 unistd.h 我们会发现,其实 wait 就是经过包装的 waitpid:
static inline pid_t wait( int * wait_stat)
{
return waitpid( - 1 ,wait_stat, 0 );
}
可以用kill函数杀死子进程
kill(childPid,SIGKILL);
子进程的结束状态返回后存于status,下面有几个宏可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
if (WIFEXITED(status))
{
printf( " exited, status=%d/n " , WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
printf( " killed by signal %d/n " , WTERMSIG(status));
}
else if (WIFSTOPPED(status)) {
printf( " stopped by signal %d/n " , WSTOPSIG(status));
}
else if (WIFCONTINUED(status)) {
printf( " continued/n " );
}
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回 - 1 。失败原因存于errno 中。
fork函数
Create a new process
程序段里用了fork();之后程序出了分岔,派生出了两个进程。具体哪个先运行就看该操作的系统的调度算法了。
函数返回2次.
返回值得在子进程中pid的值为0,通过getpid可以获取子进程的进程id;
返回值:
A value of zero to the child process; and the process ID of the child process to the parent process.
Both processes continue to execute from the fork() function. If an error occurs, fork() returns - 1 to the parent and sets errno.
#include < sys / types.h >
#include < process.h >
int main()
{
pid_t pid;
puts( " <1> " );
pid = fork();
if (pid < 0 ) {
printf( " error in fork! \r\n " );
}
else if (pid == 0 ) {
printf( " i am the child process, my process id is %d \r\n " ,getpid());
}
else {
printf( " i am the parent process, my process id is %d \r\n " ,getpid());
}
puts( " <2> " );
return 0 ;
}