C 内核空间和用户空间中段错误

来源:互联网 发布:c语言经典算法100例 编辑:程序博客网 时间:2024/04/28 16:10

      今天编写小的字符设备驱动,遇到一个很奇怪的现象。能成功挂载模块,但无法下载模块。在输入sudo rmmod main时, 出现 “MODULE is in use” 这样的错误,在dmesg 打印信息时 会出现 ” ……taint kernel….. “这样的信息。找了一晚上的bug,崩溃足可以形容我的心情。感谢师兄帮助。废话不多说,例子上来,希望能帮助像我一样的内核入门者。

代码简略,只显示主体:

struct my_cdev{      char buf[1000];     .........};​static struct my_cdev *mycdev;.................​memset(mycdev->buf, 0, sizeof(mycdev->buf));........

       就是这样挂掉了。在内核空间中内核是百之百的相信自己,内存溢出时就可能直接挂掉。在用户空间中,这样的错误就是我们常见的段错误,但因内核会检查用户空间的应用程序内存的使用情况,在运行时就会出现段错误应用程序挂掉的现象。

解决的办法很简单:

struct my_cdev{          char buf[1000];         .........};​static struct my_cdev *mycdev;.................mycdev = kmalloc(sizeof(struct my_cdev), GFP_KERNEL);// 即可​memset(mycdev->buf, 0, sizeof(mycdev->buf));........用户空间的例子:​#include#include#includestruct string {       char buf[100];      int size;​};​int main(void){        struct string *str;//      str = (struct string*)malloc(sizeof(struct string));​        str->buf = "1111111";​      return 0;}

      如果不加注释那行,gcc编译通过,但运行时,就挂掉了。因为struct string *str 仅仅是在栈中开辟了8个字节的大小(指针的大小为8B)。然而并不是这结构体的大小,所以会挂掉。解决的办法有两种:第一:如例子所示去掉注释即可,这样会在堆中申请出struct​ string 结构体的大小。并str指向结构体在堆中所在的起始位置。第二: 将struct string *str 改为struct string str也可,这样会在栈中申请出struct string 结构体大小。

      Kenneth A.Reek的《POINTERS ON C》(《C和指针》)在第六章指针中也有明确的说明:“声明一个指向整型的指针都不会“创建”用于存储整型值的内存空间“

0 0
原创粉丝点击