Drive learning-daily notes day2

[1] Review
1. Types of drivers
Character device drivers: visit according to byte stream and visit sequentially.
90% of devices correspond to character device drivers.
Frame buffer device driver: LCD
block device driver: access according to block, the unit of access is 512 bytes,
it can be accessed sequentially or out of order.
Network card device driver: devices related to network communication

2.内核模块
	入口
	static int __init demo_init(void)
	{
		//在安装驱动的时候执行
		//资源分配
		return 0;
	}
	module_init(demo_init);
	
	出口
	static void __exit demo_exit(void)
	{
		//在卸载的时候执行
		//资源释放	
	}
	
	module_exit(demo_exit);
	许可证
	MODULE_LICENSE("GPL");
	
3.编译
	内部编译:在内核源码树中进行编译
		Kconfig .config Makefile
	外部编译:在内核源码树外进行编译
	Makefile:
		KERNELDIR:=/lib/modules/$(shell uname -r)/build/
		#KERNELDIR:=/home/linux/kernel/kernel-3.4.39/
		PWD:=$(shell pwd)
		
		modules:
			make -C $(KERNELDIR) M=$(PWD) modules
	
		clean:
			make -C $(KERNELDIR) M=$(PWD) clean
		obj-m:=demo.o
	
	静态编译:
		将驱动编译到uImage中,它是内部模块
	动态编译:
		编译生成外部模块xxx.ko,在运行的时候必须依赖uImage
		
	
4.打印
	printk(打印级别 "想打印的内容");
	printk("想打印的内容");  //使用默认打印级别
	
	cat /proc/sys/kernel/printk
	4  4   1   7
	su root
	echo  4  3 1 7 > /proc/sys/kernel/printk
	
	dmesg 主动查看内核的打印信息
	sudo dmesg -C
	sudo dmesg -c
5.模块传参
	module_param(变量名,变量类型,权限);
	MODULE_PARM_DESC(变量名,"描述字段");
	
6.作业:
1.通过命令行传参的形式传递字符类型
	//只能传递整数,不能传递字符
2.通过命令行传参的形式传递字符串
	//在命令行中不允许传递空格
3.通过命令行传参的形式传递数组
module_param_array(name, type, nump, perm) 
功能:接收整型的数组
参数:
	@name :数组名
	@type :数组的类型
	@nump :命令行传递的参数的个数
	@perm :权限

sudo insmod demo.ko light=50 tt=65
	p="www.hqyj.com" ww=11,22,33

[2] Exporting the symbol table in the kernel module Exporting the symbol table
allows one kernel module to call a
function in another kernel module, which can make Linux more concise and prevent
code redundancy. It can also make
it easier for driver engineers to write complex drivers.

EXPORT_SYMBOL_GPL(sym)  
功能:将函数或者变量的符号表导出
参数:
	@sym:函数名或者变量名


编译:
	1.先编译提供者模块,编译完之后会产生一个
	Module.symvers,这个文件中记录的就是函
	数的名字及地址
	
	2.在编译调用者前需要将Module.symvers拷贝到
	调用者目录下,然后执行make,如果不拷贝会提示
	add undefined
安装:
	先安装提供者,在安装调用者
卸载:
	先卸载调用者,在卸载提供者

[3] Character device driver
User space:

open    read   write    close

	/dev/myled(c字符设备文件)

-----------------|----------------------------
Kernel space: |
Character device driver
------------ struct file_operations{ | led_open | int (*open)(); | led_write| int (*read)(); mycdev.ko | led_read | int (*write )(); | led_close| int (*close)() ------------ }; ---------------|------ ------------------------ Hardware layer: LED






vi -t register_chrdev

int register_chrdev(unsigned int major,
const char *name,
const struct file_operations *fops)
function: register a character device driver
Parameters:
@major: major device number
major>0 The system thinks this major is the major device number
major=0 system automatically assigns A major device number

设备号(32位)=主设备号(高12)+次设备号(低20)
主设备号:它是哪一类设备 LED UART BEEP WDT
次设备号:同类中的第几个设备

@name :给你的字符设备驱动起的名字
	通过 cat /proc/devices 可以查看
	Character devices:
	  1 		mem
	  4 		/dev/vc/0
	  4 		tty
	  4 		ttyS
	  5 		/dev/tty
	  5 		/dev/console
	  5 		/dev/ptmx
	  5 		ttyprintk
	  6 		lp
	  7 		vcs
	  |          |
	  主设备号  名字

@fops:操作方法结构体
	vi  -t file_operations
	struct file_operations {
		ssize_t (*read) (struct file *,
			char __user *, size_t, loff_t *);
			
		ssize_t (*write) (struct file *, 
			const char __user *, size_t, loff_t *);
		int (*open) (struct inode *, struct file *);
		int (*release) (struct inode *, struct file *);
	}

Return value:
major>0 returns 0 if success, error code (negative number) if failure,
major=0 returns major device number if success, error code if failure


vi -t unregister_chrdev
void unregister_chrdev(unsigned int major, const char *name)
Function: unregister a character device driver
Parameters:
@major: major device number
@name: name
Return value: none

指定驱动文件的tags就是内核顶层的tags
:set tags=/home/linux/kernel/kernel-3.4.39/tags

[4] Test process of the
driver 1. Install the driver
sudo insmod mycdev.ko

2.查看字符设备驱动是否创建成功
	cat /proc/devices 
	250       mycdev
	|          |
	主设备号  名字
3.创建设备文件(mknod)
	sudo mknod 路径(任意)/设备文件的名字  c/b  主设备号   次设备号
	sudo mknod /dev/mycdev c 250 0
	
	
4.编写应用程序
	在应用程序中调用open  read  write  close函数
	
	
5.执行应用程序
	sudo ./a.out
	或者
	sudo chmod 777 /dev/mycdev
	./a.out
6.查看
	dmesg
	如果看到驱动中的open read  write close都打印了
	说明,应用程序调用驱动就成功了。
	
练习:
	在给大家10分钟的时间练习字符设备驱动

[5] User space and kernel space data transfer
. There are asm/uaccess.h or asm-generic/uaccess.h in the kernel.
The functions are all of the same type. If you include one of the header files, it
may be In the current kernel version, the compilation can pass, but if you
change the kernel version, the compilation will fail. Replace the previous asm with
linux/uaccess.h. This is a link file that can always be linked to the correct
header file location.

#include <linux/uaccess.h>

unsigned long copy_from_user(void *to, 
	const void __user *from, unsigned long n)
功能:将数据从用户空间拷贝到内核空间
参数:
	@to  :内核空间的首地址
	@from:用户空间的首地址
	@n   :拷贝的字节的个数
返回值:
	成功返回0,失败返回未拷贝的字节的个数
	
内核中错误码问题:
	vi -t EIO;
	
unsigned long copy_to_user(void __user *to, 
	const void *from, unsigned long n)

功能:将数据从内核空间拷贝到用户空间
参数:
	@to  :用户空间的首地址
	@from:内核空间的首地址
	@n   :拷贝的字节的个数
返回值:
	成功返回0,失败返回未拷贝的字节的个数

[6] Interaction process
between driver and hardware Since the driver runs in the virtual address of 3-4G, the
control register of the LED light is the physical address. So if you want to
manipulate physical addresses in the kernel space , you need to map physical addresses to virtual addresses.

void *ioremap(phys_addr_t offset, unsigned long size)   
功能:将物理地址映射成虚拟地址
参数:
	@offset:物理地址
	@size  :映射的长度(字节)
返回值:成功返回虚拟地址,失败返回NULL


void iounmap(void *addr)                                          
功能:取消映射
参数:
	@addr:虚拟地址
返回值:无

[7] The process of source insight creation index
1. Decompress the kernel Unzip
the source code of the kernel in the system transplantation class on windows
(you cannot share this kernel code with ubuntu through a shared directory)

2.创建索引的工程
	project->new project->填写工程的名字,选择内核源码
	的路径->ok ->ok-->选中内核源码目录-->add all-->
	会看到有3万多个文件--->close
3.创建索引
	project->sychronize files->把能选的对号都选上->ok 

Guess you like

Origin blog.csdn.net/weixin_48430195/article/details/108671773