天下

记录修行的印记

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;
}

posted on 2012-08-09 14:36 天下 阅读(2058) 评论(0)  编辑 收藏 引用 所属分类: Linux编程


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

常用链接

留言簿(4)

随笔分类(377)

随笔档案(327)

链接

最新随笔

搜索

最新评论