JZ2440笔记:字符设备驱动程序之LED驱动程序_编写编译1

(1) vi first_drv.c(模块加载模板)

int first_drv_init(void)
{
        return 0;
}

void first_drv_exit(void)
{
}

module_init(first_drv_init); 
module_exit(first_drv_exit); 

make得到

error: type defaults to 'int' in declaration of 'module_init' [-Werror=implicit-int]

error: type defaults to 'int' in declaration of 'module_exit' [-Werror=implicit-int]

于是增加 头文件 #include <linux/module.h>,make得到

WARNING: modpost: missing MODULE_LICENSE() in /home/embedfire/linux/nfs/3/first_drv.o

于是增加  MODULE_LICENSE("GPL");   make通过。

完整代码为:

#include <linux/module.h>
int first_drv_init(void)
{
        return 0;
}

void first_drv_exit(void)
{
}

module_init(first_drv_init); 
module_exit(first_drv_exit); 

MODULE_LICENSE("GPL");

在板子上操作:

# insmod first_drv.ko
first_drv: loading out-of-tree module taints kernel.
# lsmod
first_drv 669 0 - Live 0xbf000000 (O)
# rmmod

注意:vi编辑时,dd删除光标所在行后会上移,DD删除后会留下空白行。

(2) vi first_drv.c(file_operations)

#include <linux/module.h>

static int first_drv_open(struct inode *inode,struct file *file)
{
        return 0;
}

static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t len,loff_t *ppos)
{
        return 0;
}


static struct file_operations first_drv_fops = {
        .open = first_drv_open,
        .write = first_drv_write,
};


static int first_drv_init(void)
{
        printk("first_drv_init");
        return 0;
}

static void first_drv_exit(void)
{
        printk("first_drv_exit");
}

module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL");

make得到

error: variable 'first_drv_fops' has initializer but incomplete type

error: unknown field 'open' specified in initializer

error: unknown field 'write' specified in initializer

增加头文件#include <linux/fs.h>,make得到

warning: 'first_drv_fops' defined but not used [-Wunused-variable]

在板子上操作为:

# insmod first_drv.ko
# lsmod
first_drv 854 0 - Live 0xbf008000 (O)
# rmmod first_drv
first_drv_init
first_drv_exit

怎么回事,在rmmod时一起打印?printk("first_drv_init");和printk("first_drv_exit");改为printk("first_drv_init\n");和printk("first_drv_exit\n");

呵呵,没有回车则字符串会一起缓存再显示到屏幕。

最后的代码为:

#include <linux/fs.h>
#include <linux/module.h>

static int first_drv_open(struct inode *inode,struct file *file)
{
        printk("first_drv_open\n");
        return 0;
}

static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t len,loff_t *ppos)
{
        printk("first_drv_write\n");
        return 0;
}


static struct file_operations first_drv_fops = {
        .owner = THIS_MODULE,
        .open = first_drv_open,
        .write = first_drv_write,
};


static int first_drv_init(void)
{
        printk("first_drv_init\n");
        return 0;
}

static void first_drv_exit(void)
{
        printk("first_drv_exit\n");
}

module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL");

注意:1、.owner = THIS_MODULE有什么用?感觉有无影响不大。Linux kernel 笔记 (39)——"THIS_MODULE" | 我的站点 (nanxiao.me)

2、file_operations结构体的初始化为什么加“点”?C99标准,可以不用按结构体成员顺序赋值。linux内核结构体初始化时出现的.owner = THIS_MODULE是什么?-CSDN博客

3、# lsmod出现的first_drv 854 0 - Live 0xbf00c000 (O)中,854不是设备号。

  1. 模块名称first_drv 是模块的名称,表示这是一个名为 "first_drv" 的内核模块。

  2. 大小854 表示该模块占用的内核空间大小,单位通常是字节(bytes)。

  3. 使用计数0 表示没有其他模块或系统组件正在使用这个模块。使用计数通常会随着模块被引用或使用而增加。

  4. 依赖项- 表示该模块没有任何依赖的其他模块。如果模块依赖于其他模块,这里会列出它们的名称。

  5. 状态Live 表示模块当前正在运行,即已经成功加载到内核中。

  6. 内存地址0xbf00c000 是模块在内核内存空间中的地址,这表明模块已被映射到这个地址进行执行。

  7. 加载选项(O) 表示模块是以 O 或 opt(可选)标志加载的。这意味着在加载模块时可能指定了某些选项,但具体选项没有在输出中显示。

(3) vi first_drv.c(字符设备驱动注册)

#include <linux/fs.h>
#include <linux/module.h>

static int first_drv_open(struct inode *inode,struct file *file)
{
        printk("first_drv_open\n");
        return 0;
}

static ssize_t first_drv_write(struct file *file,const char __user *buf,size_t len,loff_t *ppos)
{
        printk("first_drv_write\n");
        return 0;
}


static struct file_operations first_drv_fops = {
        .owner = THIS_MODULE,
        .open = first_drv_open,
        .write = first_drv_write,
};


static int first_drv_init(void)
{
        register_chrdev(250,"first_drv",&first_drv_fops);
        printk("first_drv_init\n");
        return 0;
}

static void first_drv_exit(void)
{
        unregister_chrdev(250,"first_drv");
        printk("first_drv_exit\n");
}

module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL");

make通过。

# insmod first_drv.ko
first_drv_init
# lsmod
first_drv 1313 0 - Live 0xbf01c000 (O)
 # cat /proc/devices
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 89 i2c
 90 mtd
116 alsa
128 ptm
136 pts
153 spi
180 usb
189 usb_device
204 ttySAC
249 hidraw
250 ttySDIO
251 rpmb
252 watchdog
253 rtc
254 gpiochip

???250不是first_drv,已经先被占领了。first_drv.c中修改为111,再试。有了。
111 first_drv

测试下驱动吧,vi firstdrvtest.c

void main(void)
{
        int fd;

        fd = open("/dev/xxx",O_RDWR);
        if(fd<0)
                printf("can't open /dev/xxx !\n");
}

make得到

warning: implicit declaration of function 'open' [-Wimplicit-function-declaration]

error: 'O_RDWR' undeclared (first use in this function)

warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]

于是 man 2 open,得到并在.c中添加头文件#include <sys/types.h>,#include <sys/stat.h>,#include <fcntl.h>后编译还有警告:

 warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]

于是man 3 printf,得到并在.c中添加头文件 #include <stdio.h>后编译通过。

在板子上测试 :

# ./firstdrvtest
can't open /dev/xxx !
没有此文件,用mknod添加此文件Usage: mknod [-m MODE] NAME TYPE [MAJOR MINOR]

 mknod /dev/xxx c 111 0

再试,成功打开设备文件,现在可以使用此驱动的操作函数了。

# ./firstdrvtest
first_drv_open

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值