fs2410学习(二)

买了本中文的ldd3,都说中文的翻译差劲,可是英文实在太费劲

看了模块和字符驱动,下面是最简单的应用吧

#include <linux/module.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>

int hello_open(struct inode *,struct file *);
int hello_release(struct inode *,struct file *);
struct  file_operations hello_fops=
{
    .owner = THIS_MODULE,
    .open  = hello_open,
    .release = hello_release,
};

int hello_open(struct inode *pNode,struct file *pFile)
{
    try_module_get(THIS_MODULE);
    return 0;
}

int hello_release(struct inode *pNode,struct file *pFile)
{
    module_put(THIS_MODULE);
    return 0;
}

struct cdev  *hello_cdev ;
static struct class *led_class;
dev_t dev;
static int hello_init(void)
{
    int iMajor;
    int result;

    result = alloc_chrdev_region(&dev,0,1,"hello");
    if (result < 0)
    {
        printk("alloc_chrdev_region error\n");
        return 0;
    }
    iMajor = MAJOR(dev);
    
    hello_cdev = cdev_alloc();
    cdev_init(hello_cdev,&hello_fops);
    hello_cdev->owner = THIS_MODULE;
    cdev_add(hello_cdev,dev,1);
    

    led_class = class_create(THIS_MODULE,"hello");
    if (!led_class)
    {
        printk(KERN_ALERT"create class error\n");
        return 0;
    }
    device_create(led_class,NULL,dev,NULL,"hello%d",MINOR(dev));
    printk(KERN_ALERT "HELLO,WORLD\n");
    return 0;
}

static void hello_exit(void)
{

    cdev_del(hello_cdev);
    unregister_chrdev_region(dev,1);
    device_destroy(led_class,dev);
    class_destroy(led_class);
    printk(KERN_ALERT "GOODBYE\n");

}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");



分三段

第一段 初识模块

1.必须编译内核树

   进入内核根目录,make modules,make modules_install install(ps:用的是自己下载的2.6.35内核)

   此时内核树路劲在/lib/modules/2.6.35

2.新手必写,hello world

static int hello_init(void)
{

	printk(KERN_ALERT "HELLO,WORLD\n");
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_ALERT "GOODBYE\n");

}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

3.Makefile

借鉴的lld3

CROSS_COMPILE = /home/sprink/toolchain/bin/arm-sprink-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
CFLAGS=

ifneq ($(KERNELRELEASE),)
	obj-m := hello.o
else
	KERNELDIR ?= /lib/modules/2.6.35/build/ 
	PWD := $(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
	mv hello.c hello
	rm -rf hello.*
	mv hello hello.c

endif


第二阶段 初识字符设备

ldd3上讲的scull设备说实话没搞明白干什么用的。只明白了既然是设备,就必须得用设备号

1.设备号

有主设备号和次设备号,主设备号是和字符设备驱动关联的,次设备号是给内核使用的(此类设备的个数,一般从0开始,不知道这样理解有没有错误)。MKDEV,MAJOR,MINOR。

建立字符设备的第一件事就是获得一个或者多个设备编号,于是就有了动态注册和静态注册

register_chrdev;

register_chrdev_region;

alloc_chrdev_region;

register_chrdev是之前的内核使用的,可以动态或者静态分配一个设备号。现在可以用,但是既然出现了替代者,我们还是使用替代者的好。

register_chrdev_region(dev_t first,unsigned int count,char *name);是静态分配一个设备号。但是出于管理需要,最好是动态分配。

也就是使用alloc_chrdev_region(dev_t * dev ,unsigned int firstminor,unsigned int count,char *name);

同样unregister_chrdev_region();就是在退出模块时使用,来释放设备号。

dev_t dev;
static int hello_init(void)
{
    int iMajor;
    int result;

    result = alloc_chrdev_region(&dev,0,1,"hello");
    if (result < 0)
    {
        printk("alloc_chrdev_region error\n");
        return 0;
    }
   
    printk(KERN_ALERT "HELLO,WORLD\n");
    return 0;
}

static void hello_exit(void)
{
    unregister_chrdev_region(dev,1);
    printk(KERN_ALERT "GOODBYE\n");

}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

第三阶段 udev


第二阶段中注册设备后可以再/proc/device中看到自己的设备,但是在/dev下面却没有。

我知道的有两种方法:

1.mknod

2.udev

static struct class *led_class;
class_create;
device_create;

只知道用而已,说不出个所以然来



另:

在编译的时候出现个一个问题我就简单描述下,带下次出现时有迹可循:

两个静态全局变量

static int i = 1;

static int i = j;

第二句是错误的,编译的时候有问题

涉及静态全局变量的初识化问题,j是变量,在编译的时候是没有值的,所以编译器任务是错的















 


  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值