Understanding Unix/Linux Programming-信号与play_again4.c的准备知识

本文详细解释了在计算机系统中,按下Ctrl-C按键时发生的过程,包括如何通过信号机制终止程序,以及进程如何通过不同方式处理信号。文章还介绍了信号的基本概念、来源及其在进程控制中的作用。
  • Ctrl-C做了什么?

  Ctrl-C终止当前运行的程序,这个中断由一个称为信号的内核机制产生。信号是一个简单而重要的概念,下面将探讨信号的基本概念。

  终端驱动程序在这里起到了相应的作用:

  1. 用户输入Ctrl-C
  2. 驱动程序收到字符
  3. 匹配VINTR和ISIG的字符被开启
  4. 驱动程序调用信号系统
  5. 信号系统发送SIGINT到进程
  6. 进程收到SIGINT
  7. 进程消亡

  当然未必一定是Ctrl-C作为中断的控制字符,这是可以更改驱动设置的。

  • 什么是信号:

  信号是由单个词组成的消息。绿灯、停止标牌、裁判手势等都是信号,而这个物体和事件不是消息,走、停和出界才是消息。当按下Ctrl-C时,内核向当前正在运行的进程发送中断信号,每个信号都有一个数字编码,中断信号编码通常是2。

  信号从何处来?

  信号来自内核,生成信号请求来自于3个地方:

  1. 用户:用户通过输入控制字符请求内核产生信号
  2. 内核:当进程执行出错时,内核给进程发送一个信号,例如:非法段存取、浮点数溢出等等;内核也利用信号通知进程特定事件的发生。
  3. 进程:一个进程可以通过系统调用kill命令给另一个进程发送信号,进程之间可以通过信号通信。
    1. 由进程某个操作产生的信号被成为同步信号,例如,被零除。
    2. 由用户击键这样的外部事件产生的信号被成为异步信号

  哪里可以找到信号列表?信号编号以及它们的名字一般出现在/usr/include/signal.h中。

  例如,中断信号被成为SIGINT,退出信号为SIGQUIT,非法段存取的信号是SIGSGEV。

  信号的作用?视情况而定。很多信号杀死进程。某时刻进程还在运行,下一秒它就消亡了。从内存中被删除,相应的所有的文件描述符被关闭,并且从进程表中被删除。使用SIGINT可以消灭一个进程,但是进程也有办法保护自己不被杀死。

  • 进程如何处理信号?

  当进程接收到SIGINT时,并不一定要消亡,进程能够通过系统调用signal告诉内核,它要如何处理信号,进程有3个选择:

  • 接收组织(内核)安排:通常是消亡

    手册上会列出对每个信号的默认处理,SIGINT的默认处理是消亡,进程并不一定要使用默认处理,但是可以通过一下调用来恢复默认处理:

    signal(SIGINT , SIG_DFL);

  • 忽略信号(喂?你好?什么?我听不清!喂?我听不清!)

    程序可以通过以下调用告诉内核它要忽略SIGINT信号

    signal(SIG_INT , SIG_IGN);

  • 调用一个函数

    这当然是最灵活有用的一种咯,考虑play_again3的例子。当用户输入Ctrl-C的时候,当前程序立即退出而不调用恢复终端驱动设置恢复的函数。更好的做法时,程序在接收到SIGINT后,调用一个恢复设置的函数,然后再退出。

    调用signal的第三种选择允许这种类型的响应。程序能够告诉内核,当信号到来时,应该调用哪个函数。在信号到来时调用的函数被成为信号处理函数(越看越觉得像是单片机编程中的中断处理函数)。为安装信号处理函数,程序调用:

    signal( signum , functionname );

  signal的返回值为-1时表示错误;而正常情况下,返回一个指向(前一个处理)函数的指针。

来看看信号处理的例子吧:

 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void f(int) ;

int main()
{
    void f(int) ;
    int i ;

    signal(SIGINT , f) ; // Declare the handler

    for(i = 0 ; i < 5 ; i ++ ){
        printf("Hello!\n" );
        sleep(1) ;
    }

    return 0 ;
}

void f(int signum )
{
    printf("OUCH!\n");
}

 

很简单的例子,哈哈,下面一个例子会忽略Ctrl-C的信号,和书上不太一样,直接改上面的了:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <signal.h>
 4 
 5 void f(int) ;
 6 
 7 int main()
 8 {
 9     void f(int) ;
10     int i ;
11 
12     signal(SIGINT , SIG_IGN) ; // Declare the handler
13 
14     for(i = 0 ; i < 5 ; i ++ ){
15         printf("Hello!\n" );
16         sleep(1) ;
17     }
18 
19     return 0 ;
20 }
21 
22 void f(int signum )
23 {
24     printf("OUCH!\n");
25 }

在输出Hello!的过程中,Ctrl-C是不能产生中断的,而使用Ctrl-\是可以的,因为这个程序没有忽略或者捕捉SIGQUIT。相当于屏蔽了一个中断,却没有屏蔽另外一个中断。

  • 进程终止和为设备编程

  程序使用signal来告诉内核它需要忽略哪些信号,但是,对于程序员而言,有两个信号是不能被忽略和捕捉的,书上让我们自己去找。。。

这个我就偷个懒,以后再找咯

  •  为设备编程:

  终端控制程序的三个方面:

  1. 驱动程序的属性和设置
  2. 以应用程序的特定需求来调整驱动程序,满足这些需求
  3. 处理信号报告的错误或者处理特定事件
arm-buildroot-linux-gnueabi-gcc: WARNING: unsafe header/library path used in cross-compilation: '-I/usr/local/include' ../lib/tevent/tevent_req.c: In function '_tevent_req_create': ../lib/tevent/tevent_req.c:78:8: warning: implicit declaration of function 'talloc_pooled_object' [-Wimplicit-function-declaration] 78 | req = talloc_pooled_object( | ^~~~~~~~~~~~~~~~~~~~ ../lib/tevent/tevent_req.c:79:12: error: expected expression before 'struct' 79 | mem_ctx, struct tevent_req, 2, | ^~~~~~ The following command failed: arm-buildroot-linux-gnueabi-gcc -I../lib/zlib -DMAX_DEBUG_LEVEL=-1 -D__location__=\ -ffunction-sections -fdata-sections -I. -I/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/source3 -I/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/source3/../lib/popt -I/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/source3/../lib/iniparser/src -Iinclude -I./include -I. -I. -I./../lib/replace -I./librpc -I./.. -I./../lib/talloc -I./../lib/tevent -I../lib/tdb/include -DHAVE_CONFIG_H -I/data/red-round3/red-round3/Iplatform/openwrt/staging_dir/target-arm-openwrt-linux-uclibc-be220v1/usr/include -I/data/red-round3/red-round3/Iplatform/openwrt/staging_dir/target-arm-openwrt-linux-uclibc-be220v1/include -I/data/red-round3/red-round3/Iplatform/openwrt/staging_dir/usr-be220v1/include -I/data/red-round3/red-round3/Iplatform/openwrt/../../bcm504L04/toolchain/opt/toolchains/crosstools-arm_softfp-gcc-10.3-linux-4.19-glibc-2.32-binutils-2.36.1/usr/include -Iinclude -I./include -I. -I. -I./../lib/replace -I./librpc -I./.. -I./../lib/popt -I/usr/local/include -I/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/source3/lib -I.. -D_SAMBA_BUILD_=3 -D_SAMBA_BUILD_=3 -c ../lib/tevent/tevent_req.c -o ../lib/tevent/tevent_req.o Makefile:1675: recipe for target '../lib/tevent/tevent_req.o' failed make[4]: *** [../lib/tevent/tevent_req.o] Error 1 make[4]: Leaving directory '/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/source3' Makefile:224: recipe for target '/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/.built' failed make[3]: *** [/data/red-round3/red-round3/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-be220v1/samba-3.6.25/.built] Error 2 make[3]: Leaving directory '/data/red-round3/red-round3/Iplatform/packages/opensource/samba' package/Makefile:133: recipe for target 'package/feeds/iplatform/samba/compile' failed make[2]: *** [package/feeds/iplatform/samba/compile] Error 2 make[2]: Leaving directory '/data/red-round3/red-round3/Iplatform/openwrt' /data/red-round3/red-round3/Iplatform/openwrt/include/toplevel.mk:184: recipe for target 'package/samba/compile' failed make[1]: *** [package/samba/compile] Error 2 make[1]: Leaving directory '/data/red-round3/red-round3/Iplatform/openwrt' Makefile:234: recipe for target 'iplatform_package/samba/compile' failed make: *** [iplatform_package/samba/compile] Error 2
最新发布
11-02
<think>Hmm, the user is reporting a cross-compilation failure for Samba on an ARM platform, specifically related to unsafe header paths and missing function declarations. This appears to be a continuation of previous discussions about Samba configuration issues. Looking at the error logs, two main issues stand out: first, the compiler warning about unsafe header path '-I/usr/local/include' which indicates contamination from the host system's include directories. Second, the fatal error regarding 'talloc_pooled_object' function being implicitly declared and then a syntax error with 'struct' - classic symptoms of header file mismatch. The context suggests this is part of an OpenWRT build system. From prior interactions, I recall we've already addressed similar configuration issues, but now it's manifesting during actual compilation. The user seems quite technical, likely an embedded systems developer struggling with cross-compilation nuances. What's particularly interesting is the version conflict angle - 'talloc_pooled_object' was introduced in talloc v2.1.0, but the build system appears to be picking up older headers. The path contamination makes this worse by mixing host and target headers. The solution needs to address both the immediate compilation failure and the underlying configuration flaws. I should emphasize: 1) Complete isolation of build environments 2) Forcing internal library usage 3) Temporary patching for backward compatibility 4) Strict path sanitization. The patch approach is safer than upgrading since user is locked to Samba 3.6.25. This user clearly understands build systems but might be missing subtle cross-compilation pitfalls. The questions I'll pose should help deepen their understanding of build environment isolation and legacy system adaptation techniques. </think>### 交叉编译污染函数兼容性错误解决方案 #### 关键问题诊断 1. **路径污染警告** `-I/usr/local/include` 导致编译器错误引用宿主机头文件 2. **函数声明冲突** `talloc_pooled_object()` 在交叉编译环境中未定义 3. **语法解析失败** 因头文件污染导致 `struct tevent_req` 解析异常 #### 完整修复方案 ##### 1. 清除路径污染(关键步骤) ```bash # 永久移除污染路径 export CFLAGS=$(echo $CFLAGS | sed 's|-I/usr/local/include||g') export LDFLAGS=$(echo $LDFLAGS | sed 's|-L/usr/local/lib||g') # 验证清除效果 echo $CFLAGS | grep -q "/usr/local" || echo "清除成功" ``` ##### 2. 强制使用内部talloc库 修改配置参数: ```diff CONFIGURE_ARGS += \ ... ++ --with-libtalloc=internal \ ++ --with-libtevent=internal \ ``` ##### 3. 应用运行时兼容补丁 ```patch --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -75,7 +75,12 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void *async_private, const char *type) { - struct tevent_req *req; + struct tevent_req *req = NULL; + +#if defined(HAVE_TALLOC_POOLED_OBJECT) + req = talloc_pooled_object(mem_ctx, struct tevent_req, 2, 0); +#else + req = talloc(mem_ctx, struct tevent_req); +#endif - req = talloc_pooled_object(mem_ctx, struct tevent_req, 2); if (req == NULL) return NULL; ``` ##### 4. 添加编译宏定义 ```bash # 禁用缺失函数 export CFLAGS="$CFLAGS -DHAVE_TALLOC_POOLED_OBJECT=0" # 添加ARM信号宏 export CFLAGS="$CFLAGS -DTEVENT_NUM_SIGNALS=64" ``` #### 验证流程 ```bash # 清理重建 make distclean # 应用补丁 patch -p1 < tevent_fix.patch # 重新配置 ./configure $CONFIGURE_ARGS # 编译测试 make V=1 ../lib/tevent/tevent_req.o 2>&1 | grep "talloc_pooled_object" ``` > **紧急替代方案**:若仍失败,在配置中禁用tevent模块: > ```bash > CONFIGURE_ARGS+=" --without-libtevent" > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值