我目前正在Linux源代码树中修改perf以实现我需要的工具。
perf最初安装了一个信号处理程序(SIGUSR2的处理程序),但我想通过处理两个信号(SIGUSR1和SIGUSR2)扩展其功能
如下图所示,内核(非用户进程)连续发送两个信号。
asmlinkage long sys_pt_signal_perf(void) //new syscall No.500
{
return (long)pt_signal_perf_wrapper();
}
int pt_signal_perf_wrapper(void)
{
if(signal_perf(2) != -1) { //SIGUSR2
/* Some dummy loop */
signal_perf(1); //SIGUSR1
printk(KERN_EMERG "Marker chunk : %d\n", j);
printk(KERN_EMERG "[SEMAPHORE LOCK] Marker Chunk\n");
pt_down_interruptible(&decode_semaphore); //perf user process unlocks this semaphore lock
printk(KERN_EMERG "Decoding for this syscall seems to be finished\n");
return 1;
}
else {
return 0;
}
}
EXPORT_SYMBOL(pt_signal_perf_wrapper);
int signal_perf(int sig_type)
{
int signal_to_send;
if(sig_type == 1)
signal_to_send = SIGUSR1;
else
signal_to_send = SIGUSR2;
if(!perf_pid) {
return -1;
}
if(!target_pid) {
return -1;
}
struct siginfo info;
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = signal_to_send;
info.si_code = SI_QUEUE;
info.si_int = SI_USER;
struct task_struct *t = find_task_by_vpid(perf_pid);
if(!t) {
printk(KERN_EMERG "No task struct for %d!\n", perf_pid);
return -1;
}
int send_sig_info_result = send_sig_info(signal_to_send, &info, t);
if(send_sig_info_result < 0)
printk(KERN_EMERG "KKM : Error sending signal!!\n");
else
printk(KERN_EMERG "KKM : sending signal successful!!\n");
return (long)perf_pid;
}
信号接收器perf作为用户进程运行。
static sigset_t pt_sigset;
...(在主要功能中)
signal(SIGUSR2, snapshot_sig_handler);
signal(SIGUSR1, snapshot_sig_handler);
/* set pt_sigset to block SIGUSR1/2 when they are being processed */
sigemptyset(&pt_sigset);
if(sigaddset(&pt_sigset, SIGUSR1) == -1) {
pr_err("sigaddset for SIGUSR1 returned -1\n");
return -1;
}
if(sigaddset(&pt_sigset, SIGUSR2) == -1) {
pr_err("sigaddset for SIGUSR2 returned -1\n");
return -1;
}
在信号处理程序中,当收到信号(SIGUSR1或SIGUSR2)时,它会使用sigprocmask阻塞SIGUSR1和SIGUSR2信号。
static void snapshot_sig_handler(int sig __maybe_unused)
{
pr_err("Blocking the two signals\n");
if(sigprocmask(SIG_BLOCK, &pt_sigset, NULL) == -1) {
pr_err("sigprocmask returned with error\n");
}
if(sig == SIGUSR2) {
pr_err("SIG_HANDLER from a non-marker chunk\n");
}
else if(sig == SIGUSR1) {
pr_err("SIG_HANDLER from a marker chunk\n");
}
else {
pr_err("NOT A VALID SIGNAL!\n");
return;
}
/* Real operation which is omitted here */
}
未显示解锁这两个信号,但肯定存在。
但是当我实际运行代码时,在某些情况下,即使两个信号都被解除阻塞,也会调用信号处理函数。 (如下所示)
Blocking the two signals
SIG_HANDLER from a non-marker chunk
Blocking the two signals
SIG_HANDLER from a marker chunk
Unblocking the two signals
Unblocking the two signals
虽然sigprocmask()没有返回错误,但似乎两个信号的阻塞似乎永远不会起作用。
这是因为信号是从更高的权限发送的吗?(kernel-&gt; user)与大多数信号事务在两个用户进程之间完成的情况不同?
非常感谢你。