第一个驱动--手工创建设备节点

先学习linux下的open函数 的用法,我们使用open打开一个设备节点

 fd=open("/dev/xxx",O_RDWR);

 

 应用程序open调用驱动就是打开设备/dev/下设备节点文件。

本篇博客    的 驱动没有自动生成设备节点信息,需要手工创建设备节点,才能使用。

 

 

 

int fd = open(参数1,参数2,参数3);

int fd = open(const char *pathname,int flags,mode_t mode);

1.句柄(file descriptor 简称fd)

2.使用open前需要先包含头文件
#include <sys/types.h>
#inlcude <sys/stat.h>
#inlcude <fcntl.h>

3.参数1(pathname)

4.参数2(flags)
flags分为两类:主类,副类
主类:O_RDONLY 以只读方式打开   /   O_WRONLY 以只写方式打开   /O_RDWR 以可读可写方式打开
三这是互斥的

副类:O_CREAT 如果文件不存在则创建该文件
O_EXCL 如果使用O_CREAT选项且文件存在,则返回错误消息
O_NOCTTY 如果文件为终端,那么终端不可以调用open系统调用的那个进程的控制终端
O_TRUNC 如果文件已经存在泽删除文件中原有数据
O_APPEND 以追加的方式打开
主副可以配合使用,例如:O_RDWR|O_CREAT|O_TRUNC

5.参数3(mode)
mode:如果文件被新建,指定其权限未mode
mode是八进制权限码,0777表示文件所有者   该文件用户组     其他用户都有可读可写可执行权限

 

/dev/xxx这个设备文件怎么来的

1、手工创建 mknod /dev/xxx c 主设备号 次设备号
2、自动创建 在/sys/目录下,busybox文件系统有mdev机制,
根据系统信息,注册驱动会自动在sys生成信息,mdev会根据这些信息
自动创建设备节点。
如果驱动里面提供这些系统信息,mdev机制就会自己在/dev/下创建xxx设备节点


本篇博客为驱动没有自动生成设备节点信息,手工创建设备节点,才能使用

 

cw_run.c应用程序

交叉编译器编译驱动

复制到nfs目录给开发板用

book@book-desktop:/work/chenwei$ arm-linux-gcc -o cw_run cw_run.c
book@book-desktop:/work/chenwei$ cp cw_run  /work/nfs_root/first_fs
 ./cw_run.c

执行应用程序
# ./cw_run 
can't open!!!!!!!

查看设备的驱动号
# cat /proc/devices 
252 chenwei_first

确实设备名为xxx的设备节点不存在
# ls /dev/xxx
ls: /dev/xxx: No such file or directory


# mknod /dev/xxx c 252 0
# ./cw_run
cw_open
cw_write


/*测试程序

  打开一个/dev/下的文件,设备节点都在该目录

*/


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>





int main(int argc,char **argv)
{
   
  int fd;
  int val=1;
  fd=open("/dev/xxx",O_RDWR);
  if(fd<0)
   printf("can't open!!!!!!!\n");
   write(fd,&val,4);
 
  return 0;
}

/*
编译本文件被拷贝到开发板
book@book-desktop:/work/chenwei$ arm-linux-gcc -o cw_run cw_run.c
book@book-desktop:/work/chenwei$ cp cw_run  /work/nfs_root/first_fs


fd=open("/dev/xxx",O_RDWR);




*/

 cw_drv.c驱动程序

使用make命令将驱动编译为.ko文件 ,复制到开发板

insmod cw_drv.ko  动态加载驱动到内核 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
static int cw_open(struct inode * inode, struct file * file)
{
    printk("cw_open\n");
	return 0;
}
static ssize_t cw_write(struct file *file,const char __user *buf, size_t count, loff_t * ppos)
{
    printk("cw_write\n");
	return 0;
}

static  struct file_operations cw_op = {
	.owner = THIS_MODULE,/* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
	.open = cw_open,
	.write = cw_write,
};

int major;

/*
# cat /proc/devices    文件里有字符设备和块设备列表
Character devices:
252 chenwei_first
主设备号 和 名字

(1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表
(2)insmod(install module,安装模块),功能是向当前内核中去安装一个模块,用法是insmod xxx.ko
(3)modinfo(module information,模块信息),功能是打印出一个内核模块的自带信息。,用法是modinfo xxx.ko,注意要加.ko,也就是说是一个静态的文件形式。
(4)rmmod(remove module,卸载模块),功能是从当前内核中卸载一个已经安装了的模块,用法是rmmod xxx.ko  rmmod xxx都可以
(5)剩下的后面再说,暂时用不到(如modprobe、depmod等)

# lsmod 
Module                  Size  Used by    Not tainted
cw_drv                  1764  0 

*/

int cw_init(void)
{  //注册设备第一个参数为0,自动分配设备号
   //不为0就看哪个设备号为空,手动分配
	major=register_chrdev(0, "chenwei_first", &cw_op);
    return 0;
}

int cw_exit(void)
{
    unregister_chrdev( major,"chenwei_first" );
	return 0;
}
module_init(cw_init);
module_exit(cw_exit);
MODULE_LICENSE("GPL");
 

Makeifile注意大写

KERN_DIR = /work/system/linux-2.6.22.6

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

obj-m	+= first_drv.o


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值