-
310 #define class_create(owner, name) \
-
311 ({ \
-
312 static struct lock_class_key __key; \
-
313 __class_create(owner, name, &__key); \
- 314 })
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/kernel.h>
-
-
#include <linux/device.h>//class_create
-
-
struct class *mem_class;
-
-
static int __init class_create_destroy_init(void)
-
{
-
printk("class_create_destroy_init init..\n");
-
mem_class = class_create(THIS_MODULE,"ywx_dev");
-
if(IS_ERR(mem_class))
-
{
-
printk("err:failed create class\n");
-
return -1;
-
}
-
printk("class create suceess\n");
-
return 0;
-
}
-
-
static void __exit class_create_destroy_exit(void)
-
{
-
printk("leaving class...\n");
-
class_destroy(mem_class);
-
printk("leaving finished.\n");
-
}
-
-
MODULE_LICENSE("GPL");
-
module_init(class_create_destroy_init);
- module_exit(class_create_destroy_exit);
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
insmod ./class_create_destroy.ko
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
dmesg | tail -8
-
[ 2360.949466] class_create_destroy_init init..
-
[ 2360.949956] class create
suceess
- //在/sys/class/下生成我們自己建立的設備的邏輯類
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
ls /sys/class | grep
ywx
-
ywx_dev
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
rmmod class_create_destroy
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
dmesg | tail -8
-
[ 2360.949466] class_create_destroy_init init..
-
[ 2360.949956] class create
suceess
-
[ 2431.145922] leaving class...
-
[ 2431.149030] leaving finished.
-
root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
ls /sys/class | grep
ywx
- root@ywx:/home/ywx/desktop/module/api_/class_create_destroy#
前面章節“class 類 class_create class_destroy”瞭解了 class_create使用,這章節中介紹device_create device_destroy使用,並通過這兩章節內容 自動建立備文件節點
- extern struct device *device_create(struct class *cls, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
在剛開始寫Linux設備驅動程序的時候,很多時候都是利用mknod命令手動創建設備節點,實際上Linux內核爲我們提供了一組函數,可以用來在模塊加載的時候自動在/dev目錄下創建相應設備節點,並在卸載模塊時刪除該節點,當然前提條件是用戶空間移植了udev。什麼事udev??請查看“ 收集 3個介紹uedv 網址資料 ”
內核中定義了struct class結構體,顧名思義,一個struct class結構體類型變量對應一個類,內核同時提供了class_create(…)函數,可以用它來創建一個類,這個類存放於sysfs下面,一旦創建好了這個類,再調用device_create(…)函數來在/dev目錄下創建相應的設備節點。這樣,加載模塊的時候,用戶空間中的udev會自動響應device_create(…)函數,去/sysfs下尋找對應的類從而創建設備節點。
在下面的例子中具體說明關係!!!!!!!!
-
ywx@ywx:/sys/class$ ls
ywx_class_char
- ywx_device_char
-
ywx@ywx:/dev$ ls -l ywx_device_char
- crw------- 1 root root 240, 0 2012-01-03 15:40 ywx_device_char
-
ywx@ywx:/sys/devices/virtual/ywx_class_char/ywx_device_char$
ls -la
-
total 0
-
drwxr-xr-x 3 root root 0 2012-01-03
15:40 .
-
drwxr-xr-x 3 root root 0 2012-01-03
15:40 ..
-
-r--r--r-- 1
root root 4096 2012-01-03 16:10 dev
這個就是我們在驅動中分配的大小4KB
-
drwxr-xr-x 2 root root 0 2012-01-03
16:10 power
-
lrwxrwxrwx 1 root root 0 2012-01-03 15:40
subsystem -> ../../../../class/ywx_class_char符號鏈接設備
- -rw-r--r-- 1 root root 4096 2012-01-03 15:40 uevent
-
#include <linux/kernel.h>
-
#include <linux/module.h>
-
#include <linux/init.h>
-
-
#include <linux/cdev.h>
-
#include <linux/device.h>
-
#include <linux/slab.h>//kmalloc
-
#include <linux/vmalloc.h>//vmalloc()
-
#include <linux/types.h>//ssize_t
-
#include <linux/fs.h>//file_operaiotns
-
#include <linux/uaccess.h>//copy_from_user
-
-
#define MEM_MALLOC_SIZE 4096 ////緩衝區大小
-
#define MEM_MAJOR 240 ////主設備號
-
#define MEM_MINOR 0
-
-
char *mem_spvm = NULL; ////緩衝區指針,指向內存區
-
struct cdev *mem_cdev = NULL; //字符設備對象指針
-
struct class *mem_class = NULL; //設備類指針
-
-
static int __init mem_init(void);
-
static void __exit mem_exit(void);
-
static int mem_open(struct inode *inode,struct
file *filp);
-
static int mem_release(struct inode *inode, struct
file *filp);
-
static ssize_t mem_read(struct file *filp,char __user *buf,size_t
count,loff_t *fpos);
-
static ssize_t mem_write(struct file *filp, char __user *buf,size_t
count ,loff_t *fops);
-
-
static const struct file_operations mem_fops={
-
.owner = THIS_MODULE,
-
.open = mem_open,
-
.release = mem_release,
-
.read = mem_read,
-
.write = mem_write,
-
};
-
-
static int __init mem_init(void)
-
{
-
int ret;
-
//創建設備號 主次設備號
-
int devno = MKDEV(MEM_MAJOR,MEM_MINOR);
-
printk("mem_init initial...\n");
-
-
//開闢內核內存緩衝區
-
mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);
-
if(mem_spvm == NULL)
-
{
-
printk("vmalloc mem_spvm error\n");
-
return -ENOMEM;//
-
}
-
-
//
-
mem_cdev = cdev_alloc();
-
if(mem_cdev == NULL)
-
{
-
printk("cdev_alloc error\n");
-
return -ENOMEM;
-
}
-
cdev_init(mem_cdev,&mem_fops);
-
mem_cdev->owner = THIS_MODULE;
-
ret = cdev_add(mem_cdev,devno,1);//將字符設備鍵入內核系統
-
if(ret)
-
{
-
cdev_del(mem_cdev);
-
mem_cdev = NULL;
-
printk("cdev_add error\n");
-
return -1;
-
}
-
-
//
-
mem_class = class_create(THIS_MODULE,"ywx_class_char");
-
if(IS_ERR(mem_class))
-
{
-
printk("class_create error..\n");
-
return -1;
-
}
-
device_create(mem_class,NULL,MKDEV(MEM_MAJOR,MEM_MINOR),NULL,"ywx_device_char");
-
-
printk("init finished..\n");
-
return 0;
-
}
-
-
static void __exit mem_exit(void)
-
{
-
printk("mem_exit starting..\n");
-
if(mem_cdev != NULL)
-
cdev_del(mem_cdev);
-
printk("cdev_del ok\n");
-
-
device_destroy(mem_class,MKDEV(MEM_MAJOR,MEM_MINOR));
-
class_destroy(mem_class);
-
-
if(mem_spvm != NULL)
-
vfree(mem_spvm);
-
-
printk("vfree ok\n");
-
printk("mem_exit finished..\n");
-
}
-
-
static int mem_open(struct inode *inode,struct
file *filp)
-
{
-
printk("open vmalloc space..\n");
-
try_module_get(THIS_MODULE);//模塊引用計數器自加
-
printk("open vamlloc space ok..\n");
-
return 0;
-
}
-
static int mem_release(struct inode *inode, struct
file *filp)
-
{
-
printk("close vmalloc space..\n");
-
module_put(THIS_MODULE);//模塊引用計數器自減
-
return 0;
-
}
-
static ssize_t mem_read(struct file *filp,char __user *buf,size_t
count,loff_t *fpos)
-
{
-
int ret = -1;
-
char *tmp;
-
printk("copy data to the user space\n");
-
tmp = mem_spvm;
-
if(count > MEM_MALLOC_SIZE)
-
count = MEM_MALLOC_SIZE;
-
if(tmp != NULL)//將內核數據寫入到用戶空間
-
ret = copy_to_user(buf,tmp,count);
-
if(ret == 0)
-
{
-
printk("read copy data success\n");
-
return count;
-
}
-
else
-
{
-
printk("read copy data error\n");
-
return 0;
-
}
-
}
-
static ssize_t mem_write(struct file *filp, char __user *buf,size_t
count ,loff_t *fops)
-
{
-
int ret = -1;
-
char *tmp;
-
printk("read data from the user space.\n");
-
tmp = mem_spvm;
-
if(count > MEM_MALLOC_SIZE)
-
count = MEM_MALLOC_SIZE;
-
if(tmp != NULL)
-
ret = copy_from_user(tmp,buf,count);
-
if(ret == 0)
-
{
-
printk("write copy data success.\n");
-
return count;
-
}
-
else
-
{
-
printk("write copy data error.\n");
-
return 0;
-
}
-
}
-
-
MODULE_LICENSE("GPL");
-
module_init(mem_init);
- module_exit(mem_exit);
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <string.h>//memset()
-
-
int main(int argc, char *argv[])
-
{
-
int fd,cnt;
-
char buf[256];
-
int i;
-
printf("char device testing..\n");
-
fd = open("/dev/ywx_device_char",O_RDWR);
-
if(fd == 0)
-
{
-
printf("open failed.\n");
-
return 1;
-
}
-
-
printf("input the data for kernel:");
-
scanf("%s",buf);
-
cnt = write(fd,buf,256);
-
if(cnt == 0)
-
printf("write error\n");
-
-
printf("clear buf,and will read from kernel...\n");
-
for(i=0;i<256;i++)
-
buf[i] = 32;//32 ="
"
-
-
cnt = read(fd,buf,256);
-
if(cnt > 0)
-
printf("read data from kernel is:%s\n",buf);
-
else
-
printf("read data error\n");
-
close(fd);
-
printf("close app..\n");
-
return 0;
- }
-
root@ywx:/home/ywx/desktop/module/api_/cdev_init_add_del/app# ./app
-
char device testing..
-
input the data for kernel:yuweixian4230.blog.chinaunix.net
-
clear buf,and will read from kernel...
-
read data from kernel is:yuweixian4230.blog.chinaunix.net
- close app..