相关疑难解决方法(0)

如何编写信号处理程序来捕获SIGSEGV?

我想写一个信号处理程序来捕获SIGSEGV.我使用保护内存块进行读写

char *buffer;
char *p;
char a;
int pagesize = 4096;

mprotect(buffer,pagesize,PROT_NONE)
Run Code Online (Sandbox Code Playgroud)

这可以保护从缓冲区开始的内存大小字节的内存,防止任何读取或写入.

其次,我尝试读取内存:

p = buffer;
a = *p 
Run Code Online (Sandbox Code Playgroud)

这将生成一个SIGSEGV,我的处理程序将被调用.到现在为止还挺好.我的问题是,一旦调用处理程序,我想通过这样做来改变内存的访问写入

mprotect(buffer,pagesize,PROT_READ);
Run Code Online (Sandbox Code Playgroud)

并继续正常运行我的代码.我不想退出该功能.在将来写入相同内存时,我想再次捕获信号并修改写入权限,然后记录该事件.

这是代码:

#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>

#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

char *buffer;
int flag=0;

static void handler(int sig, siginfo_t *si, void *unused)
{
    printf("Got SIGSEGV at address: 0x%lx\n",(long) si->si_addr);
    printf("Implements the handler only\n");
    flag=1;
    //exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{ …
Run Code Online (Sandbox Code Playgroud)

c linux system-calls mprotect signal-handling

68
推荐指数
4
解决办法
7万
查看次数

如何从用户空间访问系统调用?

我读了LKD 1中的一些段落, 我无法理解下面的内容:

从用户空间访问系统调用

通常,C库提供对系统调用的支持.用户应用程序可以从标准头中提取函数原型并与C库链接以使用您的系统调用(或者库例程,而该库例程又使用您的系统调用).但是,如果您刚刚编写了系统调用,那么glibc已经支持它是值得怀疑的!

值得庆幸的是,Linux提供了一组用于包装系统调用访问的宏.它设置寄存器内容并发出陷阱指令.这些宏被命名,其中介于0和6之间.该数字对应于传递给系统调用的参数数量,因为宏需要知道预期的参数数量,从而推入寄存器.例如,考虑系统调用,定义为_syscalln()nopen()

long open(const char *filename, int flags, int mode)
Run Code Online (Sandbox Code Playgroud)

在没有显式库支持的情况下使用此系统调用的syscall宏将是

#define __NR_open 5
_syscall3(long, open, const char *, filename, int, flags, int, mode)
Run Code Online (Sandbox Code Playgroud)

然后,应用程序可以简单地调用open().

对于每个宏,有2 + 2×n个参数.第一个参数对应于系统调用的返回类型.第二个是系统调用的名称.接下来是系统调用顺序的每个参数的类型和名称.的__NR_open定义是在<asm/unistd.h>; 它是系统呼叫号码.的_syscall3宏扩展到与联汇编C函数; 程序集执行上一节中讨论的步骤,将系统调用号和参数推送到正确的寄存器中,并发出软件中断以陷入内核.将此宏放在应用程序中是使用open()系统调用所需的全部内容.

让我们编写宏来使用我们精彩的新foo()系统调用,然后编写一些测试代码来展示我们的努力.

#define __NR_foo 283
__syscall0(long, foo)

int main ()
{
        long stack_size;

        stack_size = foo ();
        printf ("The kernel stack size is %ld\n", stack_size);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

是什么 …

linux system-calls

17
推荐指数
2
解决办法
2万
查看次数

关于linux中匿名映射内存的问题

我正在玩弄使用虚拟内存系统的想法,允许我对我得到的一些数字数据进行透明数据转换(例如int to float).基本思想是我正在编写的库mmaps您想要的数据文件,同时mmaps一个适当大小的匿名区域来保存转换后的数据,并将此指针返回给用户.

匿名区域的读/写保护,所以,每当用户经历的指针来访问数据,每一个新的页面会造成段错误,我能赶上,然后透明地在mmaped文件转换数据,同时设置权限允许访问继续.到目前为止,整个事情的这一部分很有效.

但是,有时我会绘制非常大的文件(数百GB),并且匿名内存代理访问它,很快你就会开始吃掉交换空间,因为匿名页面会被丢弃到磁盘上.我的想法是,如果我可以在将转换后的数据写入它们之后将匿名页面上的脏位显式设置为false,那么操作系统只会删除它们,并在以后重新访问时按需填充零.

对于这个工作,虽然,我想我必须设置脏位为假,并说服OS设置页面进行阅读时,他们交换出去的保护,这样我就可以重新赶上随后的段错误,并重新转换数据一经请求.在做了一些研究后,我认为没有内核黑客攻击是不可能的,但我想我会问,看看有更多关于虚拟内存系统的人是否知道可以实现的方法.

c linux memoization memory-mapped-files

7
推荐指数
1
解决办法
3099
查看次数

在多线程程序中捕获SIGSEGV和SIGFPE等信号

我正在尝试为在linux上运行的程序编写多线程日志记录系统.

在主程序线程中调用日志记录系统会将包含要记录的数据的数据结构推送到FIFO队列中.专用线程选择队列的数据并输出数据,而程序主线程继续其任务.

如果主程序导致SIGSEGV或其他信号被引发,我需要在终止之前确保队列为空.

我的计划是使用pthread_sigmask http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html阻止除一个线程之外的所有信号,但是在http://man7.org上读取信号列表/linux/man-pages/man7/signal.7.html我注意到:

可以为整个过程(例如,当使用kill(2)发送时)或针对特定线程(例如,某些信号,例如SIGSEGV和SIGFPE,>生成的信号)生成(并因此待决)信号执行特定机器语言指令的步骤是线程定向的,使用pthread_kill(3)的特定线程的信号也是如此.

如果我在所有线程上阻塞SIGSEGV但是一个专用于捕获信号的线程,那么它会捕获由不同线程引发的SIGSEGV吗?

在Linux中发现了使用多个线程进行信号处理的问题,但我对于哪些信号是特定于线程以及如何捕获它们一无所知.

c++ linux multithreading posix

6
推荐指数
1
解决办法
2238
查看次数