Linux(程序设计):59---SIGHUP、SIGPIPE、SIGURG信号处理(附SIGURG信号处理普通数据与外带数据案例)

article/2025/11/10 5:04:29
  • 本文介绍3个与网络编程有关的3个信号

一、SIGHUP信号处理

  • 信号产生的情景:
    • 1.如果终端接口检测到一个连接断开,则将此信号送给与该终端相关的控制进程(会话首进程)
      • 此信号被送给session结构中s_leader字段所指向的进程。仅当终端的CLOCAL标志没有设置时,在上述条件下才产生此信号(如果所连接的终端是本地的,则设置该终端的CLOCAL标志。它告诉终端驱动程序忽略所有调制解调器的状态行)
      • 注意:接到此信号的会话首进程可能在后台。这区别于由终端正常产生的几个信号(中断、退出和挂起),这些信号总是传递给前台进程组
    • 2.如果会话首进程终止,也产生此信号,在此情况下,此信号送给前台进程组的每一个进程
  • 程序对此信号的默认动作为终止程序
  • 通常用此信号通知守护进程再次读取它们的配置文件。选用SIGHUP的理由是,守护进程不会有控制终端,通常绝不会接收到这种信号。一个典型的例子就是xinetd超级服务程序(见下面的演示案例)

演示案例(xinetd超级服务程序)

  • xinetd程序在接收到SIGHUP信号之后将调用hard_reconfig函数,它循环读取/etc/xinetd.g/目录下的每个子配置文件,并检测其变化
  • 如果某个正在运行的子服务的配置文件被修改以停止服务,则xinetd主程序将给该子服务进程发送SIGTERM信号以结束它。如果某个子服务的配置文件被修改以开启服务,则xinetd将创建新的socket并将其绑定到该服务对应的端口上
  • 现在来分析xinetd处理SIGHUP信号的流程。下面是检测机器的环境:
    • 从ps的输出可以看出,xinetd创建子进程7442,它运行echo-stream内部服务
    • 从lsof输出来看,xinetd打开了一个管道。该管道的读端文件描述符的值是3,写端文件描述符的值是4(这个就是我们前面介绍的统一事件源)

  • 现在我们修改/etc/xinetd.d/目录下的部分配置文件,并给xinetd发送一个SIGHUP信号,操作如下:

  • 我们使用streace命令跟踪程序执行时调用的系统调用和接收到的信号。此处我们根据进程7438(即xinetd服务器程序),输出内容如下,每个部分用空行隔开,共4个部分:
    • 第一部分:描述程序接收到SIGHUP信号时,信号处理函数使用管道通知主程序该信号的到来。信号处理函数往文件描述符4(管道的写端)写入信号值1(SIGHUP信号),而主程序使用poll检测到文件描述符3(管道的读端)上有可读事件,就将管道上的数据读入
    • 第二部分:描述符了xinetd重新读取一个子配置文件的过程
    • 第三部分:描述了xinetd给子进程echo-stream(PID为7442)发送SIGTERM信号来终止该子进程,调用waitpid来等待子进程结束
    • 第四部分:描述了xinetd启动telnet服务的过程:创建一个流服务socket并将其绑定到端口23上,然后监听该端口

二、SIGPIPE信号处理

  • 信号产生的情景:
    • 如果在管道的读进程已终止时写管道,则产生此信号
    • 当类型为SOCK_STREAM的套接字已不再连接时,进程写该套接字也产生此信号
  • 程序对此信号的默认动作为终止程序
  • 引起SIGPIPE信号的写操作将设置errno为EPIPE
  • 信号处理:
    • 我们可以使用send函数的MSG_NOSIGNAL标志来禁止写操作触发SIGPIPE信号
    • 我们也可以根据errno值来判断管道或者socket连接的读端是否已经关闭
    • 我们也可以根据I/O复用系统来检测管道和socket连接的读端是否已经关闭。以poll为例,当管道的读端关闭时,写端文件描述符上的POLLHUP事件将被触发;当socket连接对对方关闭时,socket上的POLLRDHUP事件将被触发

三、SIGURG信号处理

  • 信号产生的情景:此信号通知进程已经发生了一个紧急情况。在网络连接上接到带外的数据时,可选择的产生此信号
  • 程序对此信号的默认动作为忽略此信号
  • 处理带外数据:在前面文章中(https://blog.csdn.net/qq_41453285/article/details/103126845),我们介绍了select在接收到带外数据时将返回,并向应用程序报告socket上的异常事件。此处我们可以使用SIGURG信号处理带外数据

演示案例(处理带外数据)

//sigurg.cpp
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <libgen.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>#define LISTEN_NUM  5
#define BUFFER_SIZE 1024static int client_fd; //客户端的fdvoid add_signal(int signal_no,void (*sig_handler)(int signal_no));void sig_handler(int signal_no);int main(int argc,char* argv[])
{    if(argc!=3){printf("usage:./%s [server ip] [server port]\n",basename(argv[1]));exit(EXIT_FAILURE);}const char* ip;int server_fd,port;ip=argv[1];port=atoi(argv[2]);//创建套接字if((server_fd=socket(AF_INET,SOCK_STREAM,0))==-1){perror("socket");exit(EXIT_FAILURE);}//初始化服务器地址struct sockaddr_in server_address;bzero(&server_address,sizeof(server_address));server_address.sin_family=AF_INET;server_address.sin_port=htons(port);if(inet_pton(AF_INET,ip,&server_address.sin_addr)==-1){perror("inet_pton");exit(EXIT_FAILURE);}//绑定服务端地址if(bind(server_fd,(struct sockaddr*)&server_address,sizeof(server_address))==-1){perror("bind");exit(EXIT_FAILURE);}//开启监听if(listen(server_fd,LISTEN_NUM)==-1){perror("listen");exit(EXIT_FAILURE);}//接受客户端连接struct sockaddr_in client_address;socklen_t client_address_len=sizeof(client_address);bzero(&client_address,sizeof(client_address));if((client_fd=accept(server_fd,(struct sockaddr*)&client_address,&client_address_len))==-1){perror("accept");exit(EXIT_FAILURE);}else{//添加SIGURG信号处理函数add_signal(SIGURG,sig_handler);//使用SIGURG之前,必须设置socket的宿主进程或进程组fcntl(client_fd,F_SETOWN,getpid());int recv_ret_value;char recv_buffer[BUFFER_SIZE];//接收普通数据while(1){bzero(recv_buffer,sizeof(recv_buffer));//接收数据recv_ret_value=recv(client_fd,recv_buffer,sizeof(recv_buffer-1),0);if(recv_ret_value<0){perror("recv");close(client_fd);close(server_fd);exit(EXIT_FAILURE);}else if(recv_ret_value==0){break;}else{printf("recv normal data:%s ,%d bytes\n",recv_buffer,recv_ret_value);}}close(client_fd);}close(server_fd);exit(EXIT_SUCCESS);
}void add_signal(int signal_no,void (*sig_handler)(int signal_no))
{struct sigaction act;act.sa_handler=sig_handler;sigemptyset(&act.sa_mask);act.sa_flags=0;//对信号进行处理sigaction(signal_no,&act,NULL);
}void sig_handler(int signal_no)
{//在这个信号处理函数中,我们接收带外数据int save_errno=errno;int recv_ret_value;char recv_buffer[BUFFER_SIZE];bzero(recv_buffer,sizeof(recv_buffer));//接收带外数据recv_ret_value=recv(client_fd,recv_buffer,sizeof(recv_buffer-1),0);printf("recv oob data:%s ,%d bytes\n",recv_buffer,recv_ret_value);errno=save_errno;
}
  • 测试程序:接下来我们用前面文章介绍过的一个可以发送带外数据的客户端程序(https://blog.csdn.net/qq_41453285/article/details/102984652)向这个服务端程序发送带外数据,然后测试是否是否可以收到带外数据,检测成功


http://chatgpt.dhexx.cn/article/ksAS1Tvd.shtml

相关文章

图解sql server 命令行工具sqlcmd的使用

一 操作实例 安装了sql server后此工具已经有了&#xff1b; 以sa登录&#xff1b; 打个命令&#xff0c;没反映&#xff1b; 可执行操作系统命令&#xff1b;加上!!即可&#xff1b; 查看帮助&#xff1b; 再打命令&#xff0c;也没反映&#xff1b;查询结果不显示&#xff1…

在ubuntu中使用命令行工具sqlcmd连接sql server数据库

步骤&#xff1a; 首先安装sqlcmd工具 注意&#xff1a;如果你连接的用户是 root用户&#xff0c;命令中带有 sudo 的&#xff0c;sudo都可以酌情去掉&#xff0c;不行再加上 1 安装curl软件包&#xff1a; sudo apt install curl 2 导入公共存储库 GPG 密钥 curl https:…

ssms,新建查询设置字体_如何在SSMS查询编辑器中使用SQLCMD命令

ssms,新建查询设置字体 SQLCMD Mode allows creating, testing, executing SQLCMD commands or scripts in SQL Server Management Studio directly in the query editor. This option is available since SQL Server 2005. SQLCMD模式允许直接在查询编辑器中在SQL Server Man…

使用SQLCMD在SQLServer执行多个脚本

使用SQLCMD在SQLServer执行多个脚本 概述&#xff1a; 作为DBA&#xff0c;经常要用开发人员提供的SQL脚本来更新正式数据库&#xff0c;但是一个比较合理的开发流程&#xff0c;当提交脚本给DBA执行的时候&#xff0c;可能已经有几百个sql文件&#xff0c;并且有执行顺序&…

sqlcmd命令执行大的SQL脚本

前言 这两天从服务器导出一个150多MB的脚本文件&#xff0c;导入到我本地的SQLServer数据库中时&#xff0c;直接打开执行提示内存不足的错误&#xff0c;于是google搜索发现微软针对此类情况有不少命令行工具&#xff0c;其中有一款sqlcmd 实用工具&#xff0c;官方文档地址为…

sql安装弹出sqlcmd_使用SQL Server命令行(sqlcmd)

sql安装弹出sqlcmd 介绍 (Introduction) Sqlcmd allows executing queries, T-SQL sentences and SQL Server scripts using the command line. Sqlcmd允许使用命令行执行查询&#xff0c;T-SQL语句和SQL Server脚本。 In the previous article How to work with the command…

SQL Server Management Studio 查询中使用 SQLCMD 模式

从 SQL Server 2005 开始&#xff0c;可以在 SQL Server Management Studio 查询编辑器中使用 SQLCMD 模式执行 TSQL。要在查询编辑器中编写或编辑 SQLCMD 脚本&#xff0c;需要启用 SQLCMD 模式。默认情况下&#xff0c;此模式是关闭的。 若要启用 SQLCMD 模式&#xff0c;请单…

sqlcmd去掉表头和X行受影响

使用sql语句导出到文件 sqlcmd -d test01 -U test01 -P test01 -S testdb.database.windows.net -Q "select * from test01" -o "test01.csv" -s "," -W -h-1 -k1 -d:数据库名 -U 用户名 -P 密码 -S 服务器名 -Q 执行查询后退出 -o 输出…

sqlcmd 命令

SQLCMD的介绍 文章转载自&#xff1a;http://blog.sina.com.cn/s/blog_3eec0ced0100mhm2.html 最近经常用到超过80M *.sql文件的导入问题。 上网找了一下&#xff0c;发现超过80M的文件是不能在查询分析器中执行的。 找了些解决方案&#xff0c;个人感觉最简单的方法就是这个…

cmd执行服务器sql文件命令行,Dos命令提示符下 - 用sqlcmd执行*.sql语句

Dos命令提示符下 - 用sqlcmd执行*.sql语句 1)在Dos命令下执行sqlcmd命令(当然事先需要将sqlcmd增加到环境变量中去), 2)下面白色部分替换为服务器名或计算机名即可 sqlcmd -S (local) -U sa -P 123 -d testdb -i C:\temp\data.sql 参数说明:-S 服务器地址 -U 用户名 -P 密码…

sql安装弹出sqlcmd_SQL Server中SQLCMD实用工具概述

sql安装弹出sqlcmd This article is aimed at helping you understand the sqlcmd utility. Of course, this is a tool most of us have used it at several occasions given that the tool has been around for a decade now. However, to be a solid starting point, this a…

SQLServer知识:sqlcmd用法笔记

今天给大家介绍sqlcmd用法笔记&#xff0c;希望对大家能有所帮助&#xff01; 1、介绍 sqlcmd是一个 Microsoft Win32 命令提示实用工具&#xff0c;可以通过该命令工具实现SQL语句、脚本的执行&#xff0c;并且可以实现脚本任务的自动化。 2、使用场景 2.1 针对大文件脚本的执…

Sqlcmd使用详解

Sqlcmd实用工具&#xff0c;可以输入 TRANSACT-SQL 语句、 系统过程和脚本文件&#xff0c;通过各种可用模式&#xff1a; 通过命令提示符。在中查询编辑器在 SQLCMD 模式下。在 Windows 脚本文件。在 SQL Server 代理作业的操作系统 (Cmd.exe) 作业步骤。 该实用工具使用 OD…

如何在CMD下写SQL语句

1、WinX->搜索环境变量 2、选择环境变量 3、在系统变量中找到Path&#xff0c;并双击进入 4、选择新建 5、选择安装MySQL的盘&#xff0c;找到bin&#xff0c;并复制路径到刚刚新建的Path中&#xff0c;例如笔者安装的盘是D盘 6、把复制好的路径放到Path中 7、WinR->直…

jquery设置cookie、删除cookie、获取cookie

1.引入两个js 去bootcdn搜索就行。 jquery.js <script src"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>jquery cookie <script src"https://cdn.bootcdn.net/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"…

关闭浏览器 清除cookie

根据客户要求使用dedecms v5.6版本&#xff0c;发现了一个会员登录的bug&#xff01;看来dedecms也不过如此&#xff01; 首先说说bug所在&#xff1a;在会员登录页面 /member/index.php 登录的时候 有效期如果选择‘即时’&#xff0c;那么就永远也登不上去了&#xff01; 原因…

删除cookie删不掉的问题

文章转自&#xff1a; https://blog.csdn.net/swimming_in_it_/article/details/80290547 https://blog.csdn.net/huanshiwushuang/article/details/70172536 http://php.js.cn/blog/delete-cookie/ 不知道能不能解决你的问题,但是我来说说我的经历&#xff0c;昨天在用Yii…

Javascript清除所有的cookie

只需一个js函数即可&#xff1a; //清除所有cookie函数function clearAllCookie() {var keys document.cookie.match(/[^ ;](?\)/g);if(keys) {for(var i keys.length; i--;)document.cookie keys[i] 0;expires new Date(0).toUTCString()}} 测试的所有代码如下&#xf…

JS创建、获取、删除 cookie 方法

js 创建 cookie 方法 // 没有设置 cookie 过期时间的话&#xff0c;默认是 会话cookie(浏览器关闭时&#xff0c;该cookie失效&#xff0c;被删除) document.cookie cname "" value; // 设置了过期时间的话&#xff0c;在设置的时间段内 cookie 一直存在有效&…

浏览器cookie怎么清除,彻底清除上网痕迹只需这几步

很多用户对cookie不是很了解&#xff0c;我们使用windows系统电脑浏览各个网站的时候都会产生cookie&#xff0c;cookie记录用户名、密码等信息。显而易见的是&#xff0c;cookie和网络隐私安全息息相关&#xff0c;有些恶意网站会利用cookie来侵犯用户隐私安全。因此清理cooki…