Linux——信号处理函数与阻塞状态的进程

这篇具有很好参考价值的文章主要介绍了Linux——信号处理函数与阻塞状态的进程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这篇博客记录一下我在编写一个简单的多进程回声服务器的时候出现的问题。

这个问题就在于忽略了几个有关于信号处理函数的基本常识:

  1. 用通俗的话讲信号注册函数(signal、sigaction)的功能:进程告诉操作系统,当以后收到向信号注册函数传入的信号时,你帮我调用一下信号处理函数。
  2. 当该进程在之后收到指定的信号之后,操作系统就会帮助进程调用指定的信号处理函数。但是,如果该进程处于阻塞状态,那么操作系统会强制唤醒进程!并且不会再陷入之前的阻塞!

下面是我所写的代码中的一个片段(C和C++混编出来的屎,别喷):

 void start()
    {
        // 开始接受客户端请求
        struct sigaction act;
        act.sa_handler = wait_child_proc;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        sigaction(SIGCHLD,&act,0);

        sockaddr_in client;
        socklen_t len = sizeof(client);
        while(true)
        {

            int sockfd = accept(_listenfd,(sockaddr *)&client,&len);
            if(sockfd == -1)
            {
                printf("accept error!\n");
                continue;
            }
            std::cout << "有新的客户端..." << std::endl;
            pid_t id = fork();
            if(id == 0)
            {
                close(_listenfd);//子进程不负责监听业务
                int recv_len = 0;
                char buffer[1024] = {0};
                while((recv_len = read(sockfd,buffer,sizeof(buffer))) != 0)
                {
                    std::cout << "recv_len = " << recv_len << std::endl;
                    write(sockfd,buffer,recv_len);
                }
                close(sockfd);
                std::cout << "子进程处理完业务!退出!" << getpid() << std::endl;
                exit(0);
            }
            else if(id > 0)
            {
                close(sockfd);// 父进程不处理业务
            }
            else 
            {
               std::cout << "fork error!" << std::endl;
                exit(-1);
            }
        }
    }

这段代码会有两个地方陷入阻塞:一是父进程调用accept时,二是子进程调用read时。而子进程并没有调用信号注册函数,因此子进程与本篇文章研究的问题无关。

这段代码的意思大概是这样:调用start()后,调用sigaction()注册了一个SIGCHLD信号,然后继续往下走直到accept()阻塞。如果accept()返回了一个正确的套接字,那么主进程就创建一个子进程去处理I/O。子进程当中的read()如果返回值为0,就说明连接已经断开了,此时子进程就会退出。同时,在子进程处理I/O的时候,父进程已经在accept()处阻塞了,此时如果子进程处理的I/O连接断开,子进程就会退出,父进程就会收到SIGCHLD信号,然而此时的父进程正处于阻塞状态,所以操作系统会强制唤醒父进程以便调用信号处理函数,而父进程的accept()没有收到任何可用连接并且又从accept()处唤醒,因此accept()的返回值为-1,所以会打印一个"accept error!"。

虽然这段代码并不会给服务器带来任何功能上的差错,但是一个连接断开就打印一次"accept error!"确实是比较奇怪的。因此写下该篇文章以做记录。文章来源地址https://www.toymoban.com/news/detail-539970.html

到了这里,关于Linux——信号处理函数与阻塞状态的进程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包