LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1255|回复: 5

mmap参数错误?

[复制链接]
发表于 2010-7-5 10:27:04 | 显示全部楼层 |阅读模式
我想写个程序,通过/dev/mem读取物理内存上的信息,程序只写了一半就遇到了一个错误:mmap: Invalid argument
可是我感觉我的mmap调用没有用错呀,大家帮忙看看,谢谢神牛们了
root@slackware:~/code# cat watch.c

/* * * * * * * * * * * * * * * * * * * * * *
* 基于某种理念,程序不会对任何边界条件
* 进行测试,对错误调用而引起的损失概不负责
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>

typedef char *  string;
typedef int     flag;
#define d_true  (1)
#define d_false (0)
#define d_error (-1)

#define m_strcmp(a,R,b) (strcmp ((a), (b)) R 0)

struct  parameter_list {
        int     start;  /*起始的内存地址*/
        int     offset; /*偏移量*/
        int     type;   /*打印类型,只可能是'c'(字符串)或者'x'(十六进制)*/
} list = { d_error, d_error, d_error};

int     size = 0;               /*参数列表的元素,size = argc*/
char ** parameter = NULL;       /*参数列表,parameter = argv*/

/*FSM的各种状态*/
void    deal_with_parameter (void);
void    watch_mem (void);
void    print_help (void);
/*FSM的下一个状态*/
void    (*nextstate) (void) = NULL;

/*主函数*/
int     main
(int argc, string argv[]) {

        size = argc; parameter = argv;  /*初始化参数列表*/

        nextstate = deal_with_parameter;
        /*只要下一个状态存在,就不停的在状态之间转换*/
        while (NULL != nextstate) {
                (*nextstate) ();
        }

        return 0;
}

/*查找并解析参数列表*/
void    deal_with_parameter
(void) {
        
        int     count = 0;
        char *  adr = NULL;
        string  str_tmp = NULL;

        if (NULL == (str_tmp = malloc (1 << 7))) {
                perror ("malloc to str_tmp:");
                exit (1);
        }

        /*无参数调用程序打印帮助信息并退出*/
        if (size < 2) {
                nextstate = print_help;
                return;
        }

        /*分析参数*/
        for (count = 0; count < size; ++count) {
                /*-h参数显示帮助信息*/
                if (m_strcmp (parameter[count], ==, "-h")) {
                        nextstate = print_help;
                        return;
                }

                if (1 == strlen (parameter[count])) {
                        /*查找type参数*/
                        switch (*parameter[count]) {
                                case 'c': list.type = (int)'c'; break;
                                case 'x': list.type = (int)'x'; break;
                        }
                } else {
                        /*查找起始地址和偏移量*/
                        if (NULL != ( adr = strchr (parameter[count], ':'))) {
                                /*[起始地址]:[偏移量]*/
                                strncpy (str_tmp,(parameter[count]), adr - parameter[count]);
                                if (0 == (list.start = (int)strtol (str_tmp, NULL, 16))) {
                                        list.start = d_error;
                                } else {
                                        if (0 == (list.offset = (int)strtol (adr + 1, NULL, 16))) {
                                                list.offset = d_error;
                                        }
                                }
                        }
                }
        }

        /*验证参数是否都给出*/
        if (d_error == list.start || d_error == list.offset || d_error == list.type) {
                nextstate = print_help;
        } else {
                nextstate = watch_mem;
                printf ("程序将以%s形式查看物理地址0x%x偏移0x%x以内的数据,\n"
                        "如果发现程序判断错误请立刻使用Ctrl+c终止程序,回车继续。\n",
                        'c' == list.type ? "文本" : "十六进制", list.start, list.offset);
                getchar ();
        }
        return;
}

/*查看物理内存上的数据*/
void    watch_mem
(void) {

        int     fd = open ("/dev/mem", O_RDONLY);
        int *   v_adr = malloc (list.offset * ('c' == list.type ? sizeof (char):sizeof (int)));
        
        if (-1 == fd) {
                perror ("open /dev/mem");
                exit (1);
        }
        if (NULL == v_adr) {
                perror ("malloc for ary");
                exit (1);
        }
        v_adr = mmap (0, list.offset, PROT_READ, MAP_SHARED, fd, list.start);
        if ((int)v_adr < 0) {
                perror ("mmap");
                exit (1);
        }

        printf ("%p\n", v_adr);

        return;
}

/*打印帮助信息并退出*/
void    print_help
(void) {

        char *  help_msg = "help msg\n";

        printf (help_msg);

        exit (1);
}

root@slackware:~/code#
 楼主| 发表于 2010-7-5 10:29:19 | 显示全部楼层
没想到缩进没有啦,大家不妨看看这些:
struct  parameter_list {
        int     start;  /*起始的内存地址*/
        int     offset; /*偏移量*/
        int     type;   /*打印类型,只可能是'c'(字符串)或者'x'(十六进制)*/
} list = { d_error, d_error, d_error};

int *   v_adr = malloc (list.offset * ('c' == list.type ? sizeof (char):sizeof (int)));

v_adr = mmap (0, list.offset, PROT_READ, MAP_SHARED, fd, list.start);

结果perror被执行,显示mmap: Invalid argument
回复 支持 反对

使用道具 举报

发表于 2010-7-5 13:13:18 | 显示全部楼层
mmap (0, list.offset, PROT_READ, MAP_SHARED, fd, list.start);
最后一个参数 要8字节对齐?
回复 支持 反对

使用道具 举报

发表于 2010-7-5 14:24:45 | 显示全部楼层
看错..呵呵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-7-5 14:25:52 | 显示全部楼层
我不清楚,所以来问各位神牛。
回复 支持 反对

使用道具 举报

发表于 2010-7-5 16:58:42 | 显示全部楼层
跑一下你的程序,我这里倒不是提示 mmap 错误,而是 malloc 那里。

可能是指定的内存过大了,造成非法访问,所以无法分配。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表