Linux 环境下的C语言, 关于 kill 发送信号和 signal() 函数, 具体问题在以下代码的注释处

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 环境下的C语言, 关于 kill 发送信号和 signal() 函数, 具体问题在以下代码的注释处相关的知识,希望对你有一定的参考价值。

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>

void func(int signo)
int result;
wait(&result);
if(WIFEXITED(result))
printf("处理子进程的结果: %d\n",
WEXITSTATUS(result));



int main()

signal(50, func);
pid_t pid = fork();
if(pid==0)
sleep(2);
int x=100;
kill(getppid(), 50);
exit(x);

/*
子进程给父进程发送了一个50信号,
但父进程注册了signal() 函数对该信号进行了捕获并处理,
为什么 pause() 函数还是被50信号触动了,而退出了程序呢?
却没有等下一个信号的到来。
*/
pause();
printf("程序结束, 退出!\n");
return 0;

pause()会令目前的进程暂停(进入睡眠状态), 直到被信号(signal)所中断。

当50信号触动了,pause将退出睡眠状态,执行printf和return追问

但是我如果在 pause() 前面多次 sleep() 那一个50信号将不会触动 pause() 而退出
这又是为什么. 显然你的这个回答不准确

追答

你的子进程睡眠了两秒,如果你在pause前面加上sleep(2),程序将会触动pause()而退出,如果sleep的时间大于2秒时,pause将不会触动,因为50信号在子进程睡眠两秒后发出的,那时在父进程在睡眠状态,而且pause这个函数还没执行

新手请多指教!

追问

不准确, 你说的不是我想要的答案

参考技术A pause()会令目前的进程暂停(进入睡眠状态), 直到被信号(signal)所中断

linux C语言 kill函数(向进程发送信号)

man 2 kill

KILL(2)                                                              Linux Programmer's Manual                                                             KILL(2)

NAME
       kill - send signal to a process	//向进程发送信号

SYNOPSIS
       #include <sys/types.h>
       #include <signal.h>

       int kill(pid_t pid, int sig);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       kill(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

DESCRIPTION
       The kill() system call can be used to send any signal to any process group or process.
       //kill() 系统调用可用于向任何进程组或进程发送任何信号。

       If pid is positive, then signal sig is sent to the process with the ID specified by pid.
       //如果 pid 为正数,则将信号 sig 发送到具有 pid 指定的 ID 的进程。

       If pid equals 0, then sig is sent to every process in the process group of the calling process.
       //如果 pid 等于 0,则将 sig 发送到调用进程的进程组中的每个进程。

       If  pid  equals  -1,  then  sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init), but see
       below.
       //如果 pid 等于 -1,则将 sig 发送到调用进程有权发送信号的每个进程,但进程 1 (init) 除外,但请参见下文。

       If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.
       //如果 pid 小于 -1,则将 sig 发送到 ID 为 -pid 的进程组中的每个进程。
       //关于进程组,见:[linux C语言 进程组的概念 (pgid:process group id)(领头进程、组长进程、进程组的生存期)setpgid()、setpgid()](https://dontla.blog.csdn.net/article/details/124537020)

       If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the existence of a process ID  or  process  group
       ID.
       //如果 sig 为 0,则不发送信号,但仍进行错误检查; 这可用于检查进程 ID 或进程组 ID 是否存在。

       For  a  process to have permission to send a signal it must either be privileged (under Linux: have the CAP_KILL capability), or the real or effective user
       ID of the sending process must equal the real or saved set-user-ID of the target process.  In the case of SIGCONT it suffices when the sending and  receiv‐
       ing processes belong to the same session.  (Historically, the rules were different; see NOTES.)
       //对于有权发送信号的进程,它必须具有特权(在 Linux 下:具有 CAP_KILL 能力),或者发送进程的真实或有效用户 ID 必须等于目标的真实或保存的 set-user-ID 过程。 在 SIGCONT 的情况下,发送和接收进程属于同一个会话就足够了。 (从历史上看,规则是不同的;见注释。)

RETURN VALUE
       On success (at least one signal was sent), zero is returned.  On error, -1 is returned, and errno is set appropriately.
       //成功时(至少发送了一个信号),返回零。 出错时,返回 -1,并适当设置 errno。

ERRORS
       EINVAL An invalid signal was specified.	//指定了无效信号。

       EPERM  The process does not have permission to send the signal to any of the target processes.	//该进程无权将信号发送到任何目标进程。

       ESRCH  The  pid  or  process group does not exist.  Note that an existing process might be a zombie, a process which already committed termination, but has
              not yet been wait(2)ed for.
              //pid 或进程组不存在。 请注意,现有进程可能是僵尸进程,即已提交终止但尚未等待(2)的进程。

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

NOTES
       The only signals that can be sent to process ID 1, the init process, are those for which init has explicitly installed signal handlers.  This  is  done  to
       assure the system is not brought down accidentally.
       //唯一可以发送到进程 ID 1(即 init 进程)的信号是那些 init 已为其显式安装信号处理程序的信号。 
       //这样做是为了确保系统不会意外关闭。

       POSIX.1  requires that kill(-1,sig) send sig to all processes that the calling process may send signals to, except possibly for some implementation-defined
       system processes.  Linux allows a process to signal itself, but on Linux the call kill(-1,sig) does not signal the calling process.
       //POSIX.1 要求 kill(-1,sig) 将 sig 发送到调用进程可能向其发送信号的所有进程,可能除了某些实现定义的系统进程。 
       //Linux 允许进程向自身发出信号,但在 Linux 上调用 kill(-1,sig) 不会向调用进程发出信号。

       POSIX.1 requires that if a process sends a signal to itself, and the sending thread does not have the signal blocked, and no other thread has it  unblocked
       or is waiting for it in sigwait(3), at least one unblocked signal must be delivered to the sending thread before the kill() returns.
       //POSIX.1 要求,如果一个进程向自己发送信号,并且发送线程没有阻塞该信号,并且没有其他线程解除阻塞或在 sigwait(3) 中等待它,则必须至少有一个未阻塞信号 在 kill() 返回之前传递给发送线程。

   Linux notes
       Across  different  kernel versions, Linux has enforced different rules for the permissions required for an unprivileged process to send a signal to another
       process.  In kernels 1.0 to 1.2.2, a signal could be sent if the effective user ID of the sender matched effective user ID of the target, or the real  user
       ID  of  the  sender  matched the real user ID of the target.  From kernel 1.2.3 until 1.3.77, a signal could be sent if the effective user ID of the sender
       matched either the real or effective user ID of the target.  The current rules, which conform to POSIX.1, were adopted in kernel 1.3.78.
       //在不同的内核版本中,Linux 对非特权进程向另一个进程发送信号所需的权限实施了不同的规则。
       //在内核 1.0 到 1.2.2 中,如果发送者的有效用户 ID 与目标的有效用户 ID 匹配,或者发送者的真实用户 ID 与目标的真实用户 ID 匹配,则可以发送信号。 
       //从内核 1.2.3 到 1.3.77,如果发送方的有效用户 ID 与目标的真实或有效用户 ID 匹配,则可以发送信号。 符合 POSIX.1 的当前规则在内核 1.3.78 中采用。

BUGS
       In 2.6 kernels up to and including 2.6.7, there was a bug that meant that when sending signals to a process group, kill() failed with the  error  EPERM  if
       the caller did not have permission to send the signal to any (rather than all) of the members of the process group.  Notwithstanding this error return, the
       signal was still delivered to all of the processes for which the caller had permission to signal.
       //在 2.6 内核直到2.6.7(包括 2.6.7)中,存在一个错误,当向一个进程组发送信号时,如果调用者无权将信号发送到进程组的任何(而不是所有)成员,则 kill() 失败并返回错误 EPERM。 
       //尽管有这个错误返回,信号仍然被传递到调用者有权发出信号的所有进程。

SEE ALSO
       _exit(2), killpg(2), signal(2), tkill(2), exit(3), sigqueue(3), capabilities(7), credentials(7), signal(7)

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the  latest  version
       of this page, can be found at http://www.kernel.org/doc/man-pages/.

Linux                                                                       2015-08-08                                                                     KILL(2)
 Manual page kill(2) line 36/77 (END) (press h for help or q to quit)

以上是关于Linux 环境下的C语言, 关于 kill 发送信号和 signal() 函数, 具体问题在以下代码的注释处的主要内容,如果未能解决你的问题,请参考以下文章

C语言关于数组指针的问题(linux下的gcc环境)

Elasticsearch在Linux环境下的2种运行和停止方式

c语言构造http报文,实现输入一个网址,然后下载网页源码. 比如说输入www.baidu.com,最好是在linux环境下的.

linux命令kill命令

C语言发送post请求数据程序

Linux下的进程与线程—— 信号