❶ linux中自己用sigaction函数重新实现signal函数为什么可行,而不报错不是
信号是与一定的进程相联系的。也就是说,一个进程可以决定在进程中对哪些信号进行什么样的处理。例如,一个进程可以忽略某些信号而只处理其他一些信号;另外,一个进程还可以选择如何处理信号。总之,这些总与特定的进程相联系的。因此,首先要建立其信号和进程的对应关系,这就是信号的安装登记。
Linux主要有两个函数实现信号的安装登记:signal和sigaction。其中signal在系统调用的基础上实现,是库函数。它只有两个参数,不支持信号传递信息,主要是用于前32个非实时信号的安装;而sigaction是较新的函数(由两个系统调用实现:sys_signal以及sys_rt_sigaction),有三个参数,支持信号传递信息,主要用来与sigqueue系统调用配合使用。当然,sigaction同样支持非实时信号的安装,sigaction优于signal主要体现在支持信号带有参数。
对于应用程序自行处理的信号来说,信号的生命周期要经过信号的安装登记、信号集操作、信号的发送和信号的处理四个阶段。信号的安装登记指的是在应用程序中,安装对此信号的处理方法。信号集操作的作用是用于对指定的一个或多个信号进行信号屏蔽,此阶段对有些应用程序来说并不需要。信号的发送指的是发送信号,可以通过硬件(如在终端上按下Ctrl-C)发送的信号和软件(如通过kill函数)发送的信号。信号的处理指的是操作系统对接收信号进程的处理,处理方法是先检查信号集操作函数是否对此信号进行屏蔽,如果没有屏蔽,操作系统将按信号安装函数中登记注册的处理函数完成对此进程的处理。
❷ linux用户空间 - 多进程编程(三)
管道用于有学园关系的进程之间。
管道的pipe 系统调用实际上就是创建出来两个文件描述符。
当父进P1程创建出 fd[2] 时,子进程P2 会继承父进程的所有,所以也会得到pipe 的 2个 文件描述符。
所以毫无瓜葛的两个进程,一定不会访问到彼此的pipe。无法用管道进行通信。
管道一般是单工的。f[0]读,f[1]写
管道也可以适用于 兄弟进程(只要有血缘即可)。由于管道是单工的,当两个进程之间需要双向通信,则需要两跟管道。
执行
ctrl-c(2号信号) + SIGUSR1 信号 绑了一个新函数。则 ctrl-c 无效。
查看进程的信号
号信号被捕获。
将2号信号忽略掉
9号信号 kill 和19号信号 stop 不能乱搞,只能用缺省。
其它信号甚至段信号也都可以捕获。
改变程序的执行现场,修改PC指针,有些像goto,只不过返回非0值
运行结果
making segment fault
after segment fault
程序不会死。
如果不忽略 page fault
则会产生 core mp.
不停的给data 赋值,同时每隔1s会有信号进来,打印 data的值。
理论上打印出来的结果同时为0,同时为1
但并非如此,是 0,1,交替随机的。
signal 异步的,随时都可以进来,所以打印出来的结果,并不是我想要的。
信号对于应用程序来说,很像中断对于内核,都是访问临界区数据
信号被屏蔽,延后执行。
写多线程的程序时,不要以为只有线程之间有竞争,其实信号也会有竞争
system v 的IPC 年代有些久远。
有血缘关系的进程 key_t 都是相同的。
Key 是私有key IPV PRIVATE
可能用消息队列,可能用共享内存,可能用信号量进行通讯。
利用 _pathname 路径,约定好一条路径。和tcp/ip地址很像,来生成一个key_t key, 用msg_get shm_get 得到共享内存or 信号量。
int id 可以理解为文件描述符 fd。
其中Sys V 的共享内存 最为常用。
一定要检查路径,如果仅仅有2个进程,你没有创建路径,两者都是 -1(相当于大家约定好了),那当然能通信拉。但更多的进程出现,则会有问题。
一定要检查返回值
依然依靠key,但是api 实在是太挫了。P&V 操作都是 semop. (posix 的 ipc跟为简洁)
POSIX 共享内存当然也需要一个名字,但并不是路径。
无论读进程还是写进程,都需要传入相同的名字。
如果是unbuntu 会在以下路径生成文件
其实 2和3 是1 的符号链接。 只要保证是一个就能互相通信
关键点,mmap 内存的属性修改为 private 后,产生写时,虚拟地址一样,但是物理地址已经不同了
当然 如果子进程修改了程序背景,执行了 exec,那么完全不一样了,直接修改了内存逻辑。
❸ Linux中同步信号和异步信号分别怎么解释
Linux异步信号
1.int pthread_kill(pthread_t threadid, intsigno);
向特定的线程发送信号signo
2.int pthread_sigmask(int how, const sigset_t*newmask, sigset_t *oldmask);
设置线程的信号屏蔽码
3.int sigwait(const sigset_t *set, int *sig);
阻塞线程,等待set中指定的信号之一到达,并将到达的信号存入*sig。
4.代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
//#define SIGUSRR 40;
int SIGUSRR = 40;
void* threadOne(void *arg)
{
sigset_tsigset;
intsigno;
sigemptyset(&sigset);
sigaddset(&sigset,SIGUSRR);
pthread_sigmask(SIG_BLOCK,&sigset, NULL);
while(1)
{
sigwait(&sigset,&signo);
printf("getthread cond sig!\n");
}
}
int main(int argc, char **argv)
{
if(argc != 1)
{
printf("Usage:\n");
printf("threadcond\n");
return1;
}
pthread_tthreadId;
if(pthread_create(&threadId,NULL, threadOne, NULL) != 0)
{
printf("threadcreate error! \n");
return1;
}
//structsigaction act;
//act.sa_handler=SIG_IGN;
//sigemptyset(&act.sa_mask);
//act.sa_flags=0;
//sigaction(SIGUSRR,&act,0);//设置信号SIGUSR1的处理方式忽略
usleep(1000000);
pthread_kill(threadId,SIGUSRR);
usleep(1000000);
pthread_kill(threadId,SIGUSRR);
usleep(2000000);
return0;
}
❹ linux 内核中断 用什么锁
首先我阐明一下,用锁的情况只有两种:
线程
文件
内核程序在使用的时候也脱离不了这两种锁的概念。
中断,是信号,是否要处理中断信号?或者产生中断信号?
对信号来说只有:
信号屏蔽、信号捕捉、信号排队、可重如函数等概念。
你想问的问题,我没猜测,在处理某个信号时,不想让其他信号中断,那么使用信号屏蔽字:
先设置要屏蔽的信号集,要保存的信号集,初始信号集,可供协调使用的函数有几个:
#include <signal.h>
signal(这个不建议使用,应为有些老的实现是有问题的),设置信号处理程序
sig_atomic_t 数据类型
sigprocmask,设置信号屏蔽字
sigaction,设置信号处理程序,功能跟强悍,可控性更好
sigsuspend,以原子性方式,等待某些信号发生,然后返回
你具体要做啥不清楚,但使用上面的信号相关的函数,肯定能实现你的功能。参考APUE的论述。