#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;
}
哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了
我用生成的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]#
[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文件,
你编译时加上 -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]#
[root@localhost a]# cat /proc/devices
Character devices:
.
.
.
254 hello
.
.
[root@localhost a]#
#7
你运行测试程序试试看.
#8
printk("<1>Hello,world!\n");
小生这个不明白,这句hello, world 到底输出到哪里去了?
小生这个不明白,这句hello, world 到底输出到哪里去了?
#9
还有啊,你的例子在哪页啊,我怎么也找不到完整的代码
#10
printk("<1>Hello,world!\n");
小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------
在虚拟控制台看得到
Ctrl+Alt+F1
.
.
Ctrl+Alt+F5
小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------
在虚拟控制台看得到
Ctrl+Alt+F1
.
.
Ctrl+Alt+F5
#11
printk("<1>Hello,world!\n");
用命令dmesg可看到!
用命令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");
这些东西有什么用啊?到底是怎么实现的?
再给我说说啊,谢谢
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
/* 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");
这些是一些动态配置参数的宏.在加载模块时,可以 参数 = 值 的形式动态配置.
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;
}
哪位大侠帮我看看,万分感谢!
我头都搞晕了,快不行了
我用生成的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]#
[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文件,
你编译时加上 -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]#
[root@localhost a]# cat /proc/devices
Character devices:
.
.
.
254 hello
.
.
[root@localhost a]#
#7
你运行测试程序试试看.
#8
printk("<1>Hello,world!\n");
小生这个不明白,这句hello, world 到底输出到哪里去了?
小生这个不明白,这句hello, world 到底输出到哪里去了?
#9
还有啊,你的例子在哪页啊,我怎么也找不到完整的代码
#10
printk("<1>Hello,world!\n");
小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------
在虚拟控制台看得到
Ctrl+Alt+F1
.
.
Ctrl+Alt+F5
小生这个不明白,这句hello, world 到底输出到哪里去了?
-----------------------------------------------------------------------
在虚拟控制台看得到
Ctrl+Alt+F1
.
.
Ctrl+Alt+F5
#11
printk("<1>Hello,world!\n");
用命令dmesg可看到!
用命令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");
这些东西有什么用啊?到底是怎么实现的?
再给我说说啊,谢谢
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
/* 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");
这些是一些动态配置参数的宏.在加载模块时,可以 参数 = 值 的形式动态配置.
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