我想write在信号处理程序内使用(或任何异步安全函数)将数字打印到日志或终端中.我宁愿不使用缓冲I/O.
是否有一种简单而推荐的方法可以做到这一点?
例如代替printf,我更喜欢write(或任何asyn安全功能).
void signal_handler(int sig)
{
pid_t pid;
int stat;
int old_errno = errno;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child %d terminated\n", pid);
errno = old_errno;
return;
}
Run Code Online (Sandbox Code Playgroud)
打印字符串很容易.代替printf上面我可以使用(不打印pid):
write(STDOUT_FILENO, "child terminated", 16);
Run Code Online (Sandbox Code Playgroud) 非系统调用的包装器,但类似于snprintf(),dprintf()
我只是想知道是否可以在信号处理程序中调用非异步安全函数。
引用 Linux 手册页 signal(7):
如果信号中断不安全函数的执行,并且处理程序调用不安全函数,则程序的行为是未定义的。
和TLPI:
SUSv3 指出,表 21-1(异步安全函数列表)中未列出的所有函数都被认为对于信号而言是不安全的,但指出只有当信号处理程序的调用中断了某个函数的执行时,该函数才是不安全的。不安全函数,并且处理程序本身也调用不安全函数。
我对上面引用的解释是,只有当信号处理程序没有中断非异步安全函数时,从信号处理程序调用非异步安全函数才是安全的。
例如,我安装了一个 SIGINT 处理程序,它调用一个不安全的函数,crypt(3)该函数被认为是不可重入的,即不安全的。
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);
Run Code Online (Sandbox Code Playgroud)
我还在printf()中调用了无限循环main(),并且只运行主线程。
printf()问题是对于这个简单的例子,当处理程序中断执行并调用不安全函数时,我没有看到任何不好的事情发生。AFAK,printf()将获取控制台锁并具有内部缓冲区来执行缓冲 I/O,但其状态在本例中是一致的。虽然crypt()返回一个静态分配的字符串,但它不与其他函数或线程共享。
我误解了什么吗?我希望有人澄清一下,让信号处理程序中断主程序中不安全函数的执行并且本身也调用不安全函数总是不安全的,或者在某些情况下这样做是安全的(例如上面的简单示例)?
我必须处理一个可以从大型项目中的各个地方调用的日志记录模块。我遇到的问题是,有时可能会从信号处理程序内执行的代码中调用该模块。通常,日志模块使用 localtime() 和 strftime() 包含时间数据,但当然这些调用不是异步信号安全的,如果从信号处理程序中调用,可能会导致死锁。有没有办法(在 GNU/Linux 系统上)判断我的代码当前是否在信号处理程序上下文中执行,除了例如让每个信号处理程序在处理时设置一个标志?我认为简化我们的信号处理程序会更好,但在这种情况下,我无法选择在哪里调用日志记录模块。
我的程序需要对vector<string>信号处理程序中的a 的内容执行只读访问SIGINT.(另一种方法是使用固定大小的固定长度C字符串数组.)该程序设计为在POSIX环境中运行.
是vector::operator[]和vector::size()异步安全(或信号安全)?