linux系统驱动基础学习笔记

Linux驱动:
 
角色:应用程序

API
     
操作系统
      驱动
 
    
实际硬件

功能:
1.对设备进行初始化和释放
2.把数据从内核传送到硬件和从硬件读取数据
3.检测和处理设备出现的错误

Linux驱动程序类型:
字符设备:由文件系统管理   
(通过设备文件访问)
块设备:由文件系统管理
网络设备:由协议栈管理     
(通过socket访问)

查看系统设备文件
ls -l /dev
cat /proc/devices
cat /sys/power/state

属性:文件类型   主设备号  
次设备号
设备编号:<linux/types.h>
    dev_t 
32位,12为主设备号,20位为次设备号
实际使用:<linux/kdev_t.h>
dev_t -->
主设备号,次设备号
MAJOR(dev_t dev);
MINOR(dev_t
dev);
主设备号,次设备号-->(dev_t)
MKDEV(int major,int minor)

设备驱动组成:
1.配置初始化,注册设备,检测硬件设备是否正常工作。
2.服务于I/O请求的子程序
3.中断服务子程序

1.系统运行时编译并加载,卸载模块:insmod,rmmod
2.Linux内核源代码中编译成模块,启动后用insmod,rmmod
 或者直接在源代码中加载进内核。

输出:内核编程不能使用用户态C库函数中的printf()
只能用printk().为日志机制,记录日志信息或者给出警告提示。(var/log/messages)

日志级别:默认:DEFAULT_MESSAGE_LOGLEVEL  
4
<linux/kernel.h>
 #define KERN_EMERG  
 "<0>"    /* system is unusable */
#define
KERN_ALERT    "<1>"    /* action must be
taken immediately */
#define KERN_CRIT    
"<2>"    /* critical conditions */
#define
KERN_ERR      "<3>"    /* error
conditions */
#define KERN_WARNING  "<4>"    /*
warning conditions */
#define KERN_NOTICE   "<5>"  
 /* normal but significant */
#define KERN_INFO    
"<6>"    /* informational */
#define
KERN_DEBUG    "<7>"    /* debug-level
messages */

当优先级小于int
console_loglevel变量的时候,消息打印到控制台上。
如果syslogd和klogd守护进程在运行的话,消息只能加进var/log/messages文件
klogd只处理内核信息,syslogd处理其他系统信息,比如应用程序

驱动程序与应用程序的区别:
1.驱动没有main,以模块初始化函数为入口
2.驱动完成初始化后不再运行,等待系统调用
3.驱动不能使用标准C库

*编译驱动到内核模板:
1.而配置Kconfig,打开linux-2.6.32.2/drivers/char/Kconfig,
找到MINI2440_HELLO_MODULE,复制一段下来,修改成:
config
MY_HELLO
        tristate "my hello
module"
        depends on
MACH_MINI2440
        default m if
MACH_MINI2440
       
help
          Mini2440 module
samples
2.在make menuconfig,可以在Device Drivers-> Character devices中看到my
hello module
选择为M

3.打开linux-2.6.32.2/drivers/char/Makefile
 
在有CONFIG_MINI2440_HELLO_MODULE下增加:
  obj-S(CONFIG_MY_HELLO) 
+=hello.o

4.回到根目录,执行:make modules
  生成:hello.ko

系统运行后编译模板基本步骤:
1.编译
      make

      即等于:make modules

Makefile中:
 
先看KERNELRELEASE是在linux内核源码中主Makefile中是否定义,如果定义,则编译生成目标文件
 
若未定义:定义:主机:KERNELDIR ?= /lib/modules/$(shell uname -r)/build

               
开发板:KERNELDIR ?=/mnt/hgfs/LinuxShared/linux-2.6.32/linux-2.6.32.2
 
即KERNELDIR是本Makefile 依赖的linux内核源码路径  ,如是交叉编译时就取开发板上运行的源码路径

make:  $(MAKE) -C $(KERNELDIR) M=$(PWD)
modules
到linux源码所在的目录执行主Makefile
并当前路径传给主Makefile,告诉主Makefile执行完后返回到当前目录,执行Makefile

2.安装模块
      insmod
hello.ko
 modprobe -r filename 加载驱动时会同时加载该模块所依赖的其他模块。

insmod 模块名 参数名=参数值

定义参数:
module_param(参数名、参数类型、参数读写属性)

static char *string_test = “this is a test”;  
static num_test = 1000;    
module_param (num_test,int,S_IRUGO);  
module_param (steing_test,charp,S_ITUGO);

3.显示模块
      lsmod |grep
hello
4.删除模块
      rmmod hello

5.获取模块信息
      modinfo
hello.ko
6.清除
     make clean

---字符驱动---

操作步骤:
//设备的探测和初始化

************************************************************
static __init
int myinit(void)
{
     
//设备探测相关的
 //1.设备的常用属性分配 -- 设备名,设备号
 //2.设备的注册

//设备初始化
 //1.驱动中使用的一系列空间分配
 //2.和设备相关的资源的初始化 --
GPIO口的定义(属性,引脚)
 return 0;
}
static __exit void
myexit(void)
{
    //注销设备
   
//释放资源
}
//IO接口的实现
//中断的处理
***********************************************************
<linux/fs.h>
struct
file_operations
{
 struct module *owner;
 loff_t (*llseek)
(struct file *, loff_t, int);
 ssize_t (*read) (struct file *, char
__user *, size_t, loff_t *);
 ssize_t (*write) (struct file *, const
char __user *, size_t, loff_t *);
 ssize_t (*aio_read) (struct kiocb *,
const struct iovec *, unsigned long, loff_t);
 ssize_t (*aio_write)
(struct kiocb *, const struct iovec *, unsigned long, loff_t);
 int
(*readdir) (struct file *, void *, filldir_t);
 unsigned int (*poll)
(struct file *, struct poll_table_struct *);
 int (*ioctl) (struct inode
*, struct file *, unsigned int, unsigned long);
 long (*unlocked_ioctl)
(struct file *, unsigned int, unsigned long);
 long (*compat_ioctl)
(struct file *, unsigned int, unsigned long);
 int (*mmap) (struct file
*, struct vm_area_struct *);
 int (*open) (struct inode *, struct file
*);
 int (*flush) (struct file *, fl_owner_t id);
 int
(*release) (struct inode *, struct file *);
 int (*fsync) (struct file
*, struct dentry *, int datasync);
 int (*aio_fsync) (struct kiocb *,
int datasync);
 int (*fasync) (int, struct file *, int);
 int
(*lock) (struct file *, int, struct file_lock *);
 ssize_t (*sendpage)
(struct file *, struct page *, int, size_t, loff_t *, int);
 unsigned
long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned
long, unsigned long);
 int (*check_flags)(int);
 int (*flock)
(struct file *, int, struct file_lock *);
 ssize_t
(*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t,
unsigned int);
 ssize_t (*splice_read)(struct file *, loff_t *, struct
pipe_inode_info *, size_t, unsigned int);
 int (*setlease)(struct file
*, long, struct file_lock **);
};

struct file
{
 /*
  * fu_list becomes invalid after
file_free is called and queued via
  * fu_rcuhead for RCU
freeing
  */
 union
 {
  struct
list_head fu_list;
  struct rcu_head
 fu_rcuhead;
 } f_u;
 struct
path  f_path;
#define f_dentry f_path.dentry
#define
f_vfsmnt f_path.mnt
 const struct
file_operations *f_op;
 spinlock_t  f_lock;  /*
f_ep_links, f_flags, no IRQ
*/
 atomic_long_t  f_count;
 unsigned int
  f_flags;
 fmode_t   f_mode;
 loff_t   f_pos;
 struct
fown_struct f_owner;
 const struct
cred *f_cred;
 struct file_ra_state f_ra;

u64   f_version;
#ifdef
CONFIG_SECURITY
 void   *f_security;
#endif
 /*
needed for tty driver, and maybe others
*/
 void   *private_data;

#ifdef CONFIG_EPOLL
 /* Used by fs/eventpoll.c to link all the hooks
to this file */
 struct list_head f_ep_links;
#endif /* #ifdef
CONFIG_EPOLL */
 struct address_space *f_mapping;
#ifdef
CONFIG_DEBUG_WRITECOUNT
 unsigned long
f_mnt_write_state;
#endif
};

FILE *fp;

<asm/uaccess.h>

unsigned long copy_from_user(void *to, const void *from, unsigned long
n);

unsigned long copy_to_user (void * to, void * from, unsigned long len);

globvar_driver.c编译后生成的ko文件加载后,通过lsmod或者cat
/proc/devices都可以查看到该设备已经在系统中加载,但是在/dev下面有生成设备文件,需要手动创建节点
[[email protected]
driver_2]# mknod /dev/globalvar c 230 0
[[email protected] driver_2]# ls
/dev

---Linux2.6内核字符驱动---

<linux/cdev.h>
struct cdev {
   struct kobject
kobj;          // 每个 cdev 都是一个
kobject
   struct module *owner;       //
指向实现驱动的模块
   const struct file_operations *ops;   //
操纵这个字符设备文件的方法
   struct list_head list;  
    // 与 cdev 对应的字符设备文件的 inode->i_devices 的链表头
  
dev_t dev;          
          // 起始设备编号
  
unsigned int count;       // 设备范围号大小
};

定义一个struct cdev类型的对象来表示当前的设备驱动
给cdev对象分配空间
初始化cdev:
cdev_init
分配设备号:regist_chrdev_region或alloc_chrdev_region
设备驱动添加到系统:cdev_add

接口实现

注销: cdev_del
      unregister_chrdev_region

linux系统驱动基础学习笔记

时间: 2024-10-08 10:28:43

linux系统驱动基础学习笔记的相关文章

linux系统构建基础学习笔记——操作

linux系统构建 ********************************************************                  ---交叉编译环境构建--- 安装arm-linux-gcc-4.3.2 (交叉编译器) tar xzvf arm-linux-gcc-4.3.2.tgz -C /cd /usr/local/arm/4.3.2/bin./arm-linux-gcc -v在/etc/bashrc文件的最后添加如下一行:   export PATH=

Introduction the naive“scull” 《linux设备驱动》 学习笔记

Introduction the naive "scull" 首先,什么是scull? scull (Simple Character Utility for Loading Localities). scull is a char driver that acts on a memory area as though it were a device. 和第一个C程序Hello world一样,他什么都不能干,却能很好的阐释怎么一步步进阶的去写驱动 blog的最后,我会给出这对于sc

linux应用编程基础学习笔记

********************************************************            --文件I/O-- 文件:文本文件:存储量大,速度慢,便于字符操作二进制文件:存储量小,速度快,便于存放中间结果 普通文件:设备文件: ---C标准函数---:Buffered I/O,高级文件系统,在用户空间开辟缓冲区,流操作(stream)#include<stdio.h> typedef struct{ int _fd;      //文件号 int _

Linux shell脚本-基础学习笔记

Linux脚本能力不是太强,最近再补习下,毕竟linux shell在日常工作中还是很普遍的, 用起来更方便.省时省力. 以下是学习笔记,偏理论,后面有几个例子,供参考. shell脚本组成元素系统命令.文本处理工具(grep\sed等).变量.条件判断.循环结构和函数 -------------------------------------------- 三剑客:grep,sed,awk,还有wc,sort,head等 ------------------------------------

Linux系统ubuntu操作学习笔记

1,swp分区:当内存不够时用swp分区顶替内存 2,语言环境检查  locale –a:可以明白系统支持什么语言 3,安装软件: apt-cache search(软件):搜索软件 apt-cache show(软件):查询安装包相关信息 sodo apt-get install(软件):安装软件 sodo apt-get remove(软件) :删除软件包 4,安装软件方法二: dpkg-i(软件).deb安装软件 dpkg-r(软件)删除包 dpkg-p(软件)删除包(包括配置文件) 5,

linux基础学习笔记——操作大全

作者:liaoyi 更新时间:2014-6-2 ****************基本操作***************** 关机 shutdown -h now    root用户               init 0              root用户halt      root+一般用户poweroff 重启shutdown -r now    root用户init6     root用户reboot            root+一般用户 注意:1.shutdown 比较灵活,可

鸟哥的Linux私房菜——基础学习篇 —— 笔记2

at 语法 == 注意,输入at之后便进入命令行模式 ------- 不管怎么样,只会执行一次. [test @test test]# at [-m] TIME (输入工作指令)[test @test test]# atq (查看当前工作流程)[test @test test]# atrm [jobnumber] (删除流程) -m :执行at规范的工作流程时,将屏幕输出结果mail给输入指令的用户TIME :时间格式,有如下几个: ================== 格式有多种,但没有可以间

c/c++unix/linux基础学习笔记-常用命令和vi的使用

linux 基本命令的使用-命令在ubuntu下面执行,有些命令通用其他linux,有些不通用. 多条命令间用;号隔开,回车后可以一起执行. clear-前屏,pwd显示当前目录,cd跳转目录. sudo [命令]  -ubuntu 下以管理员身份运行命令. 一般情况下,运行当前目录下的程序,要用 ./文件名 执行. 查看当前shell名称:ps 进入另外一个shell,直接输入shell名称:ksh/tcsh/sh/bash,退出一个shell用:exit. 切换shell命令,如:exec

Linux学习之六-Linux系统的基础优化

Linux系统的基础优化 何谓'优化'.顾名思义,优化就是采取某些措施使某个东西或者某事物变得更加优异,出色.对于Linux而言,在初期安装好系统之后,也需要对其进行一定的基础优化,可分为安全上的优化,性能上的优化,安装常用软件包等. 1.selinux的优化 查看selinux状态getenforce 临时关闭setenforce 0 永久关闭selinux 需修改相应配置文件vi /etc/selinux/config 或者利用Linux命令中的sed替换 sed -i 's#SELINUX