linux中的mprotect()函数:set protection on a region of memory

1.头文件

#include <sys/mman.h>

2.函数作用

1.mprotect() changes protection for the calling process’s memory page(s) containing any part of the address range in the interval [addr, addr+len-1]. addr must be aligned to a page boundary.
2.如果进程以破坏保护规则的方式访问内存,那么内核就会给进程产生SIGSEGV信号(如果调用进程内存访问行为侵犯了这些设置的保护属性,内核会为该进程产生 SIGSEGV (Segmentation fault,段错误)信号,并且终止该进程。)

3.函数及参数描述

int mprotect(void *addr, size_t len, int prot);

  • addr

地址,参数类型是void*

  • len

存储数据的长度

  • prot

PROT_NONE

The memory cannot be accessed at all.完全无法访问内存。

PROT_READ

The memory can be read.可以读取内存。

PROT_WRITE

The memory can be modified.内存可以修改。

PROT_EXEC

The memory can be executed.内存可以执行。

  • 返回值

On success, mprotect() returns zero. On error, -1 is returned, and errno is set appropriately.成功返回0,失败返回-1

  • 错误的原因:

1)EACCES:该内存不能设置为相应权限。这是可能发生的,比如,如果你 mmap(2) 映射一个文件为只读的,接着使用 mprotect() 标志为PROT_WRITE。
2)EINVAL:start 不是一个有效的指针,指向的不是某个内存页的开头。
3)ENOMEM:内核内部的结构体无法分配
4)ENOMEM:进程的地址空间在区间 [start, start+len] 范围内是无效,或者有一个或多个内存页没有映射。 (Before kernel 2.4.19, the error EFAULT was incorrectly produced for these cases.)

4.示例代码

#include <unistd.h>
#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;

static void
handler(int sig, siginfo_t *si, void *unused)
{
    printf("Got SIGSEGV at address: 0x%lx\n",
            (long) si->si_addr);
    exit(EXIT_FAILURE);//#define	EXIT_FAILURE	1	/* Failing exit status.  */
}

int
main(int argc, char *argv[])
{
    char *p;
    int pagesize;
    struct sigaction sa;

    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);//清空信号集
    sa.sa_sigaction = handler;
    if (sigaction(SIGSEGV, &sa, NULL) == -1)//信号集添加要屏蔽的信号
        handle_error("sigaction");

    pagesize = sysconf(_SC_PAGE_SIZE);//sysconf( _SC_PAGESIZE );  此宏查看缓存内存页面的大小;打印用%ld长整型。
    if (pagesize == -1)
        handle_error("sysconf");

    /* Allocate a buffer aligned on a page boundary;
       initial protection is PROT_READ | PROT_WRITE */

    buffer = (char*)memalign(pagesize, 4 * pagesize);//在GNU系统中,malloc或realloc返回的内存块地址都是8的倍数(如果是64位系统,则为16的倍数)。如果你需要更大的粒度,请使用memalign或valloc。这些函数在头文件“stdlib.h”中声明
                                                     //函数memalign将分配一个由size指定大小,地址是boundary的倍数的内存块。参数boundary必须是2的幂!函数memalign可以分配较大的内存块,并且可以为返回的地址指定粒度。
                                                     //使用函数valloc与使用函数memalign类似,函数valloc的内部实现里,使用页的大小作为对齐长度
    if (buffer == NULL)
        handle_error("memalign");

    printf("Start of region:        0x%lx\n", (long) buffer);

   if (mprotect(buffer + pagesize * 2, pagesize,
                PROT_READ) == -1)
        handle_error("mprotect");

    for (p = buffer ; ; )                             //就是在这一步报错的
        *(p++) = 'a';                                 //设置为可以读内存,但是却修改内存了

    printf("Loop completed\n");     /* Should never happen */
    exit(EXIT_SUCCESS);//#define	EXIT_SUCCESS	0	/* Successful exit status.  */
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值