wait和waitpid的区别

首先奉上这两个函数
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
wait和waitpid都是用来处理终止进程的,这两个函数都返回两个值:已终止的进程ID号,以及通过statloc指针返回的子进程的状态(一个整数)。如果调用wait()的进程没有终止的进程而还有一个或多个子进程还在运行,函数将会一直阻塞到现有子进程第一个终止。waitpid函数则有选项可供控制,waitpid在一个循环里可以获取所有的终止进程。pid指需要等待的进程ID,如果值为-1表示等待第一个终止的进程,options是附加选项,常用的选项是WNOHANG,即没有子进程终止时不阻塞,至于其他选项自己百度吧。
接下来看两个简单的程序看他们的区别吧
首先来看看wait()函数

这是一个简单服务器程序,返回客户端发来的内容

#include"../unix.h"//这个头文件里面放的都是会用到的头文件,太懒了就不一一列出了
void str_echo(int );//在此函数中处理客户段发来的消息
void sig_child(int );//此函数处理终止子进程
int main(int argc, char ** argv)
{
    int listenfd , connfd;
    pid_t pid;
    socklen_t cli_len;
    struct sockaddr_in cliaddr,servaddr;
    listenfd=socket(AF_INET,SOCK_STREAM,0);
    bzero(&servaddr,sizeof(servaddr) );
    servaddr.sin_family=AF_INET;//设置协议族
    servaddr.sin_port=htons(55555);//设置端口
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//设置ip地址
    bind(listenfd,(struct sockaddr *)&servaddr, sizeof(servaddr));//绑定套接字
    listen(listenfd,1024);//监听套接字
     signal( SIGCHLD, sig_child );//捕获信号
    for(;;){
        cli_len=sizeof(cliaddr);
        connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &cli_len);//接受链接
        if((pid=fork()) == 0){//当有新链接时fork()一个子进程处理链接,父进程继续等待新连接的到来
            close(listenfd);//在子进程之嗯关闭监听套接字
            str_echo(connfd);//处理链接
            exit(0);
        }
        close(connfd);
    }

    return 0;
}
void sig_child( int signal){

    pid_t pid;
    int stat;
    pid = wait(&stat);
    std::cout<<"child   "<<pid<<"  terminated"<<std::endl;
    return;
}
void str_echo(int fd){
    ssize_t n;
    char buf[1024],buf1[1024];
    again:
    while( ( n= read( fd,buf,1024) ) >0 ){

        write(fd,buf,n-1);
        bzero(&buf,sizeof(buf));
        std::cout<<buf<<n<<std::endl;
    }
}

这是客户代码

#include"../unix.h"
#define MAXSIZE 1024
void  str_cli(FILE*,int );
int main(int argc ,char ** argv)
{
    int sockfd[5],i;
    struct sockaddr_in servaddr;
    if(argc!=2){
        std::cout<<"useage: tcpcil<IPaddress>"<<std::endl;
    }
    for( i=0;i<5;i++){//这个循环向服务器发起五次连接,让服务器创建五个子进程
    sockfd[i]=socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr,sizeof(servaddr) );
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(55555);
    inet_pton(AF_INET,argv[1], &servaddr.sin_addr);
    connect(sockfd[i],(struct sockaddr *)&servaddr, sizeof(servaddr) );
    }
    str_cli(stdin,sockfd[0]);
    exit(0);
}

void str_cli(FILE* fp,int sockfd)
{
    char sendline[MAXSIZE], recvline[MAXSIZE];
    while(fgets(sendline,MAXSIZE,fp) !=NULL){
        unsigned long int  len= strlen(sendline);

        write(sockfd, sendline, len );
        if(read(sockfd,recvline,MAXSIZE)==0 ){
            std::cout<<"server terminated premature"<<std::endl;
            exit(0);
        }
        std::cout<<recvline<<std::endl;
    }


}

接下来让我们运行一下来看看会出现什么结果
这里写图片描述
正如我们所期望的服务器创建了五个子进程
然后我们试着终止客户端看会发生什么
这里写图片描述
哎呦,明明五个子进程为什么只处理了四个,那一个怎么变成僵尸进程了?重来,重新运行一次再看看结果
这里写图片描述
*,我想骂人了,这下怎么只处理了三个子进程,剩下两个僵尸,这还是随机想处理几个就处理几个啊?是不是链接断开的太快了,wait()处理不过来了把一些进程忘记了?辣么把客户端改一下,不让她一次断开,而让他一个一个来,在客户端代码str_cli(stdin,sockfd[0]);前加上如下代码

for(i=0;i<5;i++){
        close(sockfd[i]);

    }

然后在来看一下运行结果
这里写图片描述

……此处省略1w字,这下怎么还就成两个了,还是很快?那好吧,让他每断开一次睡上一会再看看

for(i=0;i<5;i++){ //每隔一秒断开一个连接
        close(sockfd[i]);
        sleep(1);
    }

再次运行
这里写图片描述
看,这下结果就正常了,所以你得慢慢来,不要急,心急是吃不了热豆腐滴。
接下来看看waitpid()函数是怎么处理的
附上服务端代码,客户端代码和未改动前的代码一样

将原服务端代码
void sig_child( int signal){

    pid_t pid;
    int stat;
    pid = wait(&stat);
    std::cout<<"child   "<<pid<<"  terminated"<<std::endl;
    return;
}
改为如下代码
void sig_child( int signal){
    pid_t pid;
    int stat;
    while((pid=waitpid(-1,&stat , WNOHANG)) > 0)
    std::cout<<"child   "<<pid<<"  terminated"<<std::endl;
    return;
}

然后运行,看看结果如何
这里写图片描述
看,一气呵成,五个子进程一次搞定,毫不拖泥带水,五个太少,辣么看看20个咋样
这里写图片描述
麼辦法,就是这么屌,依然一次搞定

现在,wait和waitpid的区别就显而易见了吧。wait不管来多少都会接受,但是能力有限,只处理一次,至于能处理多少就看运气了,运气好,多出里一些,运气不好就呵呵了,不过一个一个来还是能全部处理的,只要不蜂拥而至就行,不然就真的呵呵了。而waitpid却不一样,即使你蜂拥而至,所有来的信号都排好队,一个一个来,保证每个都会处理。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
waitwaitpid是两个用于等待子进程结束的函数,它们的本质作用是相同的。但是waitpid相比wait多了两个参数,使得编程更加灵活。具体区别如下: 1. wait只能等待任意的子进程结束,而waitpid可以等待一个特定的子进程结束。\[1\] 2. wait函数会阻塞父进程,直到等到子进程的退出才停止阻塞,而waitpid提供了一种非阻塞方式的等待。通过设置第三个参数为WNOHANG,当子进程没有结束时,waitpid会立即返回0,不会等待。\[2\] 3. waitpid支持作业控制,提供了用于检查返回状态的宏。这些宏可以解析status指针中保存的子进程的状态。\[2\] 4. waitpid的option常量包括WNOHANG和WUNTRACED。WNOHANG表示waitpid不会阻塞,如果指定的pid并未结束,直接返回。WUNTRACED表示如果子进程进入暂停执行情况,则立即返回,但不理会结束状态。\[3\] 综上所述,waitpid相比wait具有更多的功能和灵活性,可以满足更多特定的需求。 #### 引用[.reference_title] - *1* *3* [waitwaitpid区别和使用](https://blog.csdn.net/qq_41181857/article/details/106972668)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [waitwaitpid区别](https://blog.csdn.net/qq_48739372/article/details/127656002)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值