依旧不喜欢用作业本做嵌入式的学习笔记,倒是用电脑写起来有点感觉。
1、cdev结构体
struct cdev{
struct kobject kobj; /*内嵌的kobject对象*/
struct module *owner;
struct file_operations *ops;
struct list_head list;
dev_t dev; /*设备号*/
unsigned int count;
}
2、分配和释放设备号
int register_chrev_region(dev_t from, unsigned count, const char *name); /*分配指定的设备号*/
int alloc_chrdev_region(dev_t *dev,unsigned baseminor, unsigned count, const char *name); /*由系统分配一个动态设备号*/
void unregister_chrdev_region(dev_t from, unsigned count); /*释放设备号*/
3、 file_operations 结构体 cdev常用
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 *); /*从设备中同步读数据*/
unsigned int(*poll)(struct file *, struct poll_table_struct*); /*轮询函数*/
int(*ioctl)(struct inode *,struct file *, unsigned int,unsigned long);/*ioctl 函数*/
int (*mmap)(struct inode *, struct file*); /*用于请求将设备内存映射到进程地址空间*/
int (*open)(struct inode *, struct file*);
int(*release)(struct inode *, struct file*);
int (*fasync)(int ,struct file *, int); /*通知设备FASYNC标志位发生变化*/
}
4、中断屏蔽
local_irq_diable() /*屏蔽中断*/
critical section /*临界区*/
local_irq_enable() /*开中断*/
由于Linux的异步I/O、进程调度等很多重要操作都依赖于中断,中断对于内核的运行非常重要,
在屏蔽中断期间所有的中断都无法得到处理,因此长时间屏蔽只能中断是很危险的,这就要求屏蔽
了中断之后,当前的内核执行路径应当尽快地执行完临界区的代码。它适宜和自旋锁联合使用。
5、整型原子操作
void atomic_set(atomic_t *v, int i); /*设置原子变量的值为i*/
atomic_t v = AROMIC_INIT(0); /*定义原子变量v 并初始化为0*/
atomic_read(atomic_t *v); /*返回原子变量的值*/
void atomic_add(int i, atomic_t *v); //原子变量加i
void atomic_dec(int i, atomic_t *v); //原子变量减i
void atomic_inc(atomic_t *v); //原子变量增加1
void atomic_dec(atomic_t *v); //原子变量减少1
操作测试
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v);
6、位原子操作
void set_bit(nr, void *addr); //设置位
void clear_bit(nr, void *addr); //清除位
void change_bit(nv, void *addr); //改变位
test_bit(nr, void *addr); //测试位
7、自旋锁 : 自旋锁(spin lock)是一种典型的对临界资源进行互斥访问的手段。
spinlock_t lock; //定义自旋锁
spin_lock_init(lock); //初始化自旋锁
spin_lock(lock); //获得自旋锁,能够获得锁,则马上返回,否则自旋等待持有者释放锁
spin_trylock(lock); // 获得自旋锁,能够获得锁,返回为真,否则立即返回为假,不自旋等待
spin_unlock(lock) //释放自旋锁
/*自旋锁一般使用方式*/
spinlock_t lock;
spin_lock_init(&lock);
spin_lock (&lock); /*获取自旋锁,保护临界区*/
. . . . /*临界区*/
spin_unlock (&lock); //解锁
尽管用了自旋锁可以保证临界区不受别的cpu和本cpu内的抢占进程打扰,但是得到锁的代码路径
在执行临界区的时候,还可能收到中断的底半部的影响。
1) 自旋锁实际上是一个忙等待
2)自旋锁可能导致系统死锁
3)自旋锁锁定器件不能调用可能引起进程调度的函数,如copy_from_user(), copy_to_user(), kmalloc(), msleep()等。
7.1、读写自旋锁 : 自旋锁的衍生锁读写自旋锁(rwlock)可允许读的并发。
7.2、顺序锁 : 是对读写锁的一种优化,读执行单元绝对不会被写执行单元阻塞。
7.3、读-拷贝-更新 RCU (read copy update)
8、信号量
struct semaphore sem; //定义信号量
void sema_init(struct semaphore *sem, int val); //初始化信号量
void down(struct semaphore * sem); //获得信号量,会导致睡眠,因此不能在中断上下文使用
int down_interruptible(struct semaphore *sem);//进入睡眠的进程可以被信号打断,而down()不会
int trylock(struct semaphore *sem); //尝试获得sem,如果获得立刻返回0,否则返回非0,不导致睡眠,
可以在中断的上下文使用
void up(struct semaphore * sem); //释放信号量
/*信号量的一般使用*/
DECLARE_MUTEX(mount_sem); //定义并初始化信号量的宏定义
down(&mount_sem); //获取信号量,保护临界区
. . . .. .
critical section //临界区
. . . . .
up(&mount_sem); //释放信号量
分享到:
相关推荐
*/ function checkInputChar(strInput){ var forbidChar = new Array(",","-","/","//","'","%","/""); for (var i = 0;i ; i++){ if(strInput.indexOf(forbidChar[i]) >= 0){ alert("您输入的信息: "+...
嵌入式Linux下字符型设备驱动程序的开发,驱动开发入门首选~
#include<string.h>/*字符串函数*/ #include<stdlib.h>/*其它说明(exit)*/ #include<malloc.h> /*动态地址分配函数*/ struct student /*定义数据结构,链表*/ { long int number; char name[20]; int order; ...
1、删除注释,包括块注释(/**/)和行注释(//) 2、删除空白行 3、用指定数量的空格替换TAB字符 [使用方法] 1、在WINDOWS的CMD窗口中键入行命令 2、使用WINDOWS的批处理文件(.BAT) [命令格式] CommRemove [//] ...
嵌入式Linux字符设备驱动的设计与应用 嵌入式Linux字符设备驱动的设计与应用
#define NAMELEN 20 /* 姓名最大字符数 */ #define CODELEN 10 /* 学号最大字符数 */ #define minzhu 20 /*民族*/ #define FNAMELEN 80 /* 文件名最大字符数 */ #define BUFLEN 80 /* 缓冲区最大字符数 */ /* ...
#include "string.h" /*字符串函数*/ #include "mem.h" /*内存操作函数*/ #include "ctype.h" /*字符操作函数*/ #include "alloc.h" /*动态地址分配函数*/ /****变量定义*******/ typedef struct z1 /*定义数据结构*...
#include "string.h"/*字符串函数*/ #include "ctype.h" /*字符操作函数*/ #define M 50 /*定义常数表示记录数*/ typedef struct /*定义数据结构*/ { char name[20]; /*姓名*/ char units[30]; /*单位*/ char ...
/** *//** * 从一个JSON 对象字符格式中得到一个java对象 * @param jsonString * @param pojoCalss * @return */ /** *//** * 从json HASH表达式中获取一个map,改map支持嵌套功能 * @param jsonString *...
#include <string.h> /*字符串函数*/ #include <ctype.h> /*字符操作函数*/ #define UP 0x48 /*光标上移键*/ #define DOWN 0x50 /*光标下移键*/ #define LEFT 0x4b /*光标左移键*/ #define RIGHT 0x4d /*光标...
*/ 2. /** * 把日期转换为字符串 */ 3. /** * 系统默认时间 * * @return */ 4. /** * 根据参数获取日期格式 * * @param p * @return */ 5. /** * 时间转换字符串: 通用格式 * * @param date 需要转换...
#include "stdio.h" /*I/O函数*/ # include "bios.h" /*ROM...#include "string.h" /*字符串函数*/ #include "mem.h" /*内存操作函数*/ #include "ctype.h" /*字符操作函数*/ #include "alloc.h" /*动态地址分配函数*/
/* 字符函数 */ /* 返回字符表达式中最左侧字符的ASCII代码值 */ select Ascii('a') --a:97,A:65 /* 将整数ASCII代码转换为字符 */ select Char(97)--97:a,65:A /* 返回表达式中指定字符的开始位置 */ select ...
/*****输入:运算关系式******/ /*****输出:运算结果******/ .../*****可以对表达式子中非操作符和操作数的字符进行处理*****/ /*****可以识别数学中的乘号可省略原则(如:a(b+c)=a*(b+c),(b+c)a=(b+c)*a)******/
#define N 20 #define COL 100 #define ROW 40 #include "stdio.h" #include "time.h" /*系统时间函数*/ #include "graphics.h" /*图形函数*/ #include "alloc.h"/*动态地址分配...#include "ctype.h" /*字符操作函数*/
识别用户定义的初次定义的变量还是已经定义的变量还是错误字符*/ /* 2.浮点数和常量可以识别读取并输出。 */ /* 3.识别双目运算符和用户连续输入的分界符 */ /* 4.程序存在问题:不能正确区分负号和减号,统一...
/* VM area parameters */ unsigned long vm_start; unsigned long vm_end; /* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next; pgprot_t vm_page_prot; ...
可删除C源程序中的/* xxxx */的块或单行注释,及C++风格的单行注释,对于常量字符串中出现的注释不清除。文件包含Lex代码及编译的Linux下的可执行文件。编译及使用见Readme。 C注释的类型如下 // /* // * "C-style ...
#define BACK 3592 /*BackSpace键:删除当前光标位置前一个字符*/ #define CL 29440 /*ctrl+←键:从右至左,选定文本*/ #define CR 29696 /*ctrl+→键:从左到右,选定文本*/ #define Cc 11779 /*ctrl+c键:将选定...
识别用户定义的初次定义的变量还是已经定义的变量还是错误字符*/ /* 2.浮点数和常量可以识别读取并输出。 */ /* 3.识别双目运算符和用户连续输入的分界符 */ /* 3.程序存在问题:不能正确区分负号和减号,统一输出为...