还是 LINUX设备驱动程序一书中scull例子问题.

时间:2021-12-25 22:26:56
我照书上输入如下代码:

#ifndef __KERNEL__
# define __KERNEL__
#endif

#ifndef  HELLO_QUANTUM
# define HELLO_QUANTUM 4000
#endif

#ifndef  HELLO_QSET
# define HELLO_QSET 1000
#endif 

#ifndef  HELLO_NR_DEVS
# define HELLO_NR_DEVS 1
#endif

#include <linux/config.h>
#define MODULE 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>

MODULE_LICENSE("GPL");

#define HELLO_PORT_FLOOR 0x280
#define HELLO_PORT_CELL  0x300
#define HELLO_PORT_RANGE 0x010


static int hello_port_base = HELLO_PORT_FLOOR;
static int hello_port_len = HELLO_PORT_RANGE;
static int hello_major = 0;

int hello_quantum = HELLO_QUANTUM ;
int hello_qset    = HELLO_QSET;
int hello_nr_devs = HELLO_NR_DEVS;

MODULE_PARM(hello_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");
MODULE_PARM(hello_major,"i");
MODULE_PARM(hello_quantum,"i");
MODULE_PARM(hello_qset,"i");
MODULE_PARM(hello_nr_devs,"i");

struct hello_Dev * hello_devices;

struct file_operations hello_fops;
struct file_operations * hello_fop_array[]={&hello_fops};

#define HELLO_MAX_TYPE 1

#define TYPE(dev) (MINOR(dev) >> 4)
#define NUM(dev)  (MINOR(dev) & 0xf)

typedef struct hello_Dev{
        void          **data;
        struct        hello_Dev *next;
        int           quantum;
        int           qset;
        unsigned long size;
        unsigned int  access_key;
        struct        semaphore sem;
        }hello_Dev;

int hello_trim(hello_Dev *dev)
{
    hello_Dev *next,*dptr;
    int qset = dev->qset;
    int i;
    
    for( dptr = dev; dptr; dptr = next)
    {
        if (dptr->data)
        {
            for(i = 0; i < qset; i++)
            {
                if (dptr->data[i])
                    kfree(dptr->data[i]);
            }
            kfree(dptr->data);
            dptr->data = NULL;
        }
        next = dptr->next;
        if (dptr != dev)
            kfree(dptr);
    }
    dev->size = 0;
    dev->quantum = hello_quantum;
    dev->qset = hello_qset;
    dev->next = NULL;
    return 0;
}

int hello_open(struct inode* inode,struct file* filp)
{   
    hello_Dev *dev;
    int num = NUM(inode->i_rdev);
    int type = TYPE(inode->i_rdev);

    if(!filp->private_data && type )
    {   if(type > HELLO_MAX_TYPE) return -ENODEV;
        filp->f_op = hello_fop_array[type];
        return filp->f_op->open(inode,filp);
    }
    
    dev = (hello_Dev*)filp->private_data;
    if(!dev)
    {
        if(num >= hello_nr_devs) return -ENODEV;
        dev = &hello_devices[num];
        filp->private_data = dev;
    }

    MOD_INC_USE_COUNT;
  
    if((filp->f_flags & O_ACCMODE) == O_WRONLY)
    {
        if (down_interruptible(&dev->sem))
        {
            MOD_DEC_USE_COUNT;
            return -ERESTARTSYS;
        }
        hello_trim(dev);
        up(&dev->sem);
    }
    return 0;
}
    
hello_Dev *hello_follow(hello_Dev *dev,int n)
{
    while (n--)
    {
        if(!dev->next)
        {
            dev->next = kmalloc(sizeof(hello_Dev), GFP_KERNEL);
           // dev->next = kmalloc(sizeof(hello_Dev),GFP_KERNEL);
            memset(dev->next,0,sizeof(hello_Dev));
        }
        dev = dev->next;
        continue;
    }
    return dev;
}


ssize_t hello_read(struct file *filp,char * buf,size_t count,loff_t *f_pos)
{
    hello_Dev *dev = filp->private_data;
    hello_Dev *dptr;
    int quantum = dev->quantum;
    int qset = dev->qset;
    int itemsize = quantum * qset;
    int item,s_pos,q_pos,rest;
    ssize_t ret = 0;
    
    if (down_interruptible(&dev->sem))
    {
        return -ERESTARTSYS;
    }
    if (*f_pos >= dev->size)
    {
        goto out;
    }
    if (*f_pos + count > dev->size)
    {
        count = dev->size - *f_pos;
    }
    item = (long)*f_pos / itemsize;
    rest = (long)*f_pos % itemsize;
    s_pos = rest / quantum;
    q_pos = rest % quantum;

    dptr = hello_follow(dev,item);
    
    if(!dptr->data)
    {
        goto out;
    }
    if(!dptr->data[s_pos])
    {
        goto out;
    }

    if (count > quantum - q_pos)
    {
        count = quantum - q_pos;
    }
    if (copy_to_user(buf,dptr->data[s_pos] + q_pos,count))
    {
        ret = -EFAULT;
        goto out;
    }
    *f_pos += count;
    ret = count;
 
    out: 
        up(&dev->sem);
        return ret;
}

ssize_t hello_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{   
    hello_Dev *dev = filp->private_data;
    hello_Dev *dptr;
    int quantum = dev->quantum;
    int qset = dev->qset;
    int itemsize = quantum * qset;
    int item, s_pos, q_pos, rest;
    ssize_t ret = -ENOMEM;
    
    if(down_interruptible(&dev->sem))
    {
        return -ERESTARTSYS;
    }
    
    item = (long)*f_pos / itemsize;
    rest = (long)*f_pos % itemsize;
    s_pos = rest / quantum;
    q_pos = rest % quantum;
    
    dptr = hello_follow(dev,item);
    if(!dptr->data)
    {
        dptr->data = kmalloc(qset * sizeof(char *),GFP_KERNEL);
        if(!dptr->data)
        {
           goto out;
        }
        memset(dptr->data,0,qset * sizeof(char *));
    }
    if(!dptr->data[s_pos])
    {
        dptr->data[s_pos] = kmalloc(quantum,GFP_KERNEL);
        if(!dptr->data[s_pos])
        {
           goto out;
        }       
    }
    if(count > quantum - q_pos)
    {
        count = quantum - q_pos;
    }
    if(copy_from_user(dptr->data[s_pos] + q_pos,buf,count))
    {
        ret = -EFAULT;
        goto out;
    }
    *f_pos += count;
    ret = count;

    if(dev->size < *f_pos)
        dev->size = *f_pos;

    out:
        up(&dev->sem);
        return ret;
}

int hello_release(struct inode *inode,struct file *file)
{
    return 0;
}
 
struct file_operations hello_fops= {
                          open:     hello_open,
                          read:     hello_read,
                          write:    hello_write,
                          release:  hello_release};




void hello_prelease(unsigned int port,unsigned int range)
{
    release_region(port,range);
}


int __init start_init(void)
{
    printk("<1>Hello,world!\n");
    printk("<1>The process is %s (pid %i)\n",current->comm,current->pid);
    int result = register_chrdev(hello_major,"hello",&hello_fops);
    if (result < 0)
    {
        printk(KERN_WARNING "hello:can't get major %d\n",hello_major);
        return result;
    }
    if (hello_major == 0)
    {
        hello_major = result;
    }
    if (hello_major == 0) hello_major = result; 
    return 0;
}
void __exit end_cleanup(void)
{
    hello_prelease(hello_port_base,hello_port_len);
    unregister_chrdev(hello_major,"hello");
    printk("<1>Goodbye cruel world!\n");
}

module_init(start_init);
module_exit(end_cleanup);

编译能通过,但在每个调用:kmalloc 的句语上都有警告:assignment makes pointer from integer without a cast;

21 个解决方案

#1


-----------发不了这么长的帖子,接着来!

我用生成的hello.o加载没有错误,但是当我写一个测试程序时,出现段错误!
测试程序如下:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    char *device = "/dev/hello";
    int  hello_fd;
    char cBuffer[100];
    char readchar[100];
    int i,count;
    char * constchar;
    constchar = "This is a hello device driver\n";
    sprintf(cBuffer,constchar);
    printf("driver info is : %s\n",cBuffer);
    fflush(stdout);
    hello_fd = open(device,O_RDWR);
    if(hello_fd == -1)
    {
     printf("Unable to open hello device!\n");
     exit(0);
    }
    count = write(hello_fd,cBuffer,100);
    count = read(hello_fd,readchar,100);
    printf("Driver info is : %s\n",readchar);
    fflush(stdout);
    close(hello_fd);
    return 0;
}

哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了

#2


device /dev/hello建了吗?

#3


建了.

#4


我的测试没有出现段错误,而是不能打开设备.

[root@localhost a]# insmod -f hello_dev.o
Warning: kernel-module version mismatch
        hello_dev.o was compiled for kernel version 2.4.20
        while this kernel is version 2.4.20-8
Warning: loading hello_dev.o will taint the kernel: forced load
  See http://www.tux.org/lkml/#export-tainted for information about tainted modules
Module hello_dev loaded, with warnings
[root@localhost a]# lsmod
Module                  Size  Used by    Tainted: PF
hello_dev               4396   0  (unused)
.
.
.
[root@localhost a]# gcc hello_dev_test.c -o hello_dev_test
[root@localhost a]# ./hello_dev_test
driver info is : This is a hello device driver
 
Unable to open hello device!
[root@localhost a]#

#5


sourceid() 
你编译时加上 -I/usr/src/linux-2.4.20-8/include 参数,然后建立:device /dev/hello文件,

#6


已经编译出了,可以看到device /dev/hello

[root@localhost a]# cat /proc/devices
Character devices:
.
.
.
254 hello
.
.
[root@localhost a]#

#7


你运行测试程序试试看.

#8


printk("<1>Hello,world!\n");

小生这个不明白,这句hello, world 到底输出到哪里去了?

#9


还有啊,你的例子在哪页啊,我怎么也找不到完整的代码

#10


printk("<1>Hello,world!\n");

小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------

在虚拟控制台看得到

Ctrl+Alt+F1
.
.
Ctrl+Alt+F5

#11


printk("<1>Hello,world!\n");

用命令dmesg可看到!

#12


itsvirtualme(): 
这就是一个完整的例子,用一段内存虚拟一个字符设备,整个程序就是这个字符设备的驱动程序.但我测试时,出现段错误,不明白错在哪里.

#13


MODULE_PARM(hello_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");

这些东西有什么用啊?到底是怎么实现的?
再给我说说啊,谢谢

#14


include/linux/module.h

/* Used to verify parameters given to the module.  The TYPE arg should
   be a string in the following format:
    [min[-max]]{b,h,i,l,s}
   The MIN and MAX specifiers delimit the length of the array.  If MAX
   is omitted, it defaults to MIN; if both are omitted, the default is 1.
   The final character is a type specifier:
    b   byte
    h   short
    i   int
    l   long
    s   string
*/

#define MODULE_PARM(var,type)           \
const char __module_parm_##var[]        \
__attribute__((section(".modinfo"))) =      \
"parm_" __MODULE_STRING(var) "=" type

#define MODULE_PARM_DESC(var,desc)      \
const char __module_parm_desc_##var[]       \
__attribute__((section(".modinfo"))) =      \
"parm_desc_" __MODULE_STRING(var) "=" desc

#15


itsvirtualme():
MODULE_PARM(hello_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");
这些是一些动态配置参数的宏.在加载模块时,可以 参数 = 值 的形式动态配置.

#16


既然你的major number是动态发配的,你的mknod怎么调用啊?

#17


kmalloc的返回值是void *.要做一个强制转换.这个错误就没有了.

#18


我运行测试程序是,出现段错误,请问是什么回事。
有谁调试成功的吗

#19


对于pritk的输出,你可以在/var/log/messages文件里面看到。当然,如果你使用高等级的话,有可能还会在屏幕上输出。

#20


哈哈,程序终于调试通过.

#21


mark

#1


-----------发不了这么长的帖子,接着来!

我用生成的hello.o加载没有错误,但是当我写一个测试程序时,出现段错误!
测试程序如下:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    char *device = "/dev/hello";
    int  hello_fd;
    char cBuffer[100];
    char readchar[100];
    int i,count;
    char * constchar;
    constchar = "This is a hello device driver\n";
    sprintf(cBuffer,constchar);
    printf("driver info is : %s\n",cBuffer);
    fflush(stdout);
    hello_fd = open(device,O_RDWR);
    if(hello_fd == -1)
    {
     printf("Unable to open hello device!\n");
     exit(0);
    }
    count = write(hello_fd,cBuffer,100);
    count = read(hello_fd,readchar,100);
    printf("Driver info is : %s\n",readchar);
    fflush(stdout);
    close(hello_fd);
    return 0;
}

哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了

#2


device /dev/hello建了吗?

#3


建了.

#4


我的测试没有出现段错误,而是不能打开设备.

[root@localhost a]# insmod -f hello_dev.o
Warning: kernel-module version mismatch
        hello_dev.o was compiled for kernel version 2.4.20
        while this kernel is version 2.4.20-8
Warning: loading hello_dev.o will taint the kernel: forced load
  See http://www.tux.org/lkml/#export-tainted for information about tainted modules
Module hello_dev loaded, with warnings
[root@localhost a]# lsmod
Module                  Size  Used by    Tainted: PF
hello_dev               4396   0  (unused)
.
.
.
[root@localhost a]# gcc hello_dev_test.c -o hello_dev_test
[root@localhost a]# ./hello_dev_test
driver info is : This is a hello device driver
 
Unable to open hello device!
[root@localhost a]#

#5


sourceid() 
你编译时加上 -I/usr/src/linux-2.4.20-8/include 参数,然后建立:device /dev/hello文件,

#6


已经编译出了,可以看到device /dev/hello

[root@localhost a]# cat /proc/devices
Character devices:
.
.
.
254 hello
.
.
[root@localhost a]#

#7


你运行测试程序试试看.

#8


printk("<1>Hello,world!\n");

小生这个不明白,这句hello, world 到底输出到哪里去了?

#9


还有啊,你的例子在哪页啊,我怎么也找不到完整的代码

#10


printk("<1>Hello,world!\n");

小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------

在虚拟控制台看得到

Ctrl+Alt+F1
.
.
Ctrl+Alt+F5

#11


printk("<1>Hello,world!\n");

用命令dmesg可看到!

#12


itsvirtualme(): 
这就是一个完整的例子,用一段内存虚拟一个字符设备,整个程序就是这个字符设备的驱动程序.但我测试时,出现段错误,不明白错在哪里.

#13


MODULE_PARM(hello_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");

这些东西有什么用啊?到底是怎么实现的?
再给我说说啊,谢谢

#14


include/linux/module.h

/* Used to verify parameters given to the module.  The TYPE arg should
   be a string in the following format:
    [min[-max]]{b,h,i,l,s}
   The MIN and MAX specifiers delimit the length of the array.  If MAX
   is omitted, it defaults to MIN; if both are omitted, the default is 1.
   The final character is a type specifier:
    b   byte
    h   short
    i   int
    l   long
    s   string
*/

#define MODULE_PARM(var,type)           \
const char __module_parm_##var[]        \
__attribute__((section(".modinfo"))) =      \
"parm_" __MODULE_STRING(var) "=" type

#define MODULE_PARM_DESC(var,desc)      \
const char __module_parm_desc_##var[]       \
__attribute__((section(".modinfo"))) =      \
"parm_desc_" __MODULE_STRING(var) "=" desc

#15


itsvirtualme():
MODULE_PARM(hello_port_base,"i");
MODULE_PARM_DESC (hello_port_base,"Base I/O port for hello!");
MODULE_PARM(hello_port_len,"i");
这些是一些动态配置参数的宏.在加载模块时,可以 参数 = 值 的形式动态配置.

#16


既然你的major number是动态发配的,你的mknod怎么调用啊?

#17


kmalloc的返回值是void *.要做一个强制转换.这个错误就没有了.

#18


我运行测试程序是,出现段错误,请问是什么回事。
有谁调试成功的吗

#19


对于pritk的输出,你可以在/var/log/messages文件里面看到。当然,如果你使用高等级的话,有可能还会在屏幕上输出。

#20


哈哈,程序终于调试通过.

#21


mark