字符类设备



字符设备(顺序读写,不带缓冲)

块设备(读写顺序不固定,带读写缓冲)常用sync命令(强行写入硬件) 同步数据使数据真正写进磁盘不然可能还在缓冲区

网络设备:这家伙破坏了linux一切皆文件规则。

字符设备框架:

硬件上有个字符设备,内核中就有个cdev结构与之对应

struct cdev {

struct kobject kobj;

struct module *owner;

const struct file_operations *ops;

struct list_head list;

dev_t dev;//设备号

unsigned int count;

};

每个cdev都有个设备号

设备号(32bits)=主设备号(高12bits)+次设备号(20bits)

主设备号:代表一个类型的设备

次设备号:用于区分设备的不同个体

主设备号的选取

->静态分配

看现在内核中那些主设备号没有被使用,选择一个

查看 cat/proc/devoces已用的设备号

看内核源码目录下即Documentation\device.txt看看使用那些设备号

register_chedev_region(dev_t from,unsigned count,const char name)可以连续注册多个字符设备号

from要注册的起始设备号

count 连续注册的设备个数

name名字

dev_t  __u32  ->  unsigned int  16位和32位移植兼容性才这么设计的

#definrMINORBITS 20

MKDEV(ma(主设备号),mi(次设备号)) 他是个宏 其实源码也就做了ma<<MINORBITS|mi)

unregister_chrdev_region(dev,nsigned count)卸载字符设备

->动态分配  但不是随机分配

alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char name)

注释:

/**

* alloc_chrdev_region() - register a range of char device numbers

* @dev: output parameter for first assigned number

* @baseminor: first of the requested range of minor numbers

* @count: the number of minor numbers required

* @name: the name of the associated device or driver

*

* Allocates a range of char device numbers.  The major number will be

* chosen dynamically, and returned (along with the first minor number)

* in @dev.  Returns zero or a negative error code.

*/

获取主设备号:

MAJOR(dev)   dev>>MINORBITS

cdev的操作函数

cdev_init()//初始化cdev

void cdev_init(struct cdev *cdev, const struct file_operations *fops)

{

memset(cdev, 0, sizeof *cdev);

INIT_LIST_HEAD(&cdev->list);

kobject_init(&cdev->kobj, &ktype_cdev_default);

cdev->ops = fops;

}

cdev_add()//向内核注册cdev

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

{

p->dev = dev;

p->count = count;

return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

}

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 *);

.....

};

_exit 要逆序消除 _init产生的影响

cdev_del()

unregister_chrdev_region(dev,nsigned count)

手工创建设备节点文件

mknod /dev/xxx c 248 0

主  次

arm-none-linux-gnueabi-gcc -o

/* remove by cym 20130408 support for MT660.ko */

#if 0

//#ifdef CONFIG_SMM6260_MODEM

#if 1// liang, Pixtree also need to use ioctl interface...

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

#endif

#endif

/* end remove */

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 *, 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 **);

long (*fallocate)(struct file *file, int mode, loff_t offset,

loff_t len);

/* add by cym 20130408 support for MT6260 and Pixtree */

#if defined(CONFIG_SMM6260_MODEM) || defined(CONFIG_USE_GPIO_AS_I2C)

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

#endif

/* end add */

简单纯字符小示例:

#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/cdev.h>

MODULE_LICENSE("Dua BSD/GPL");

MODULE_AUTHOR("Songmao");

MODULE_DESCRIPTION("cdev tast");

#define TCDEV_MAJOR 0

#define TCDEV_MINOR 0

#define TCDEV_NUM 1

#define TCDEV_NAME "mytcdev"

int tcdev_major =TCDEV_MAJOR,tcdev_minor=TCDEV_MINOR;

module_param(tcdev_major,int,S_IRWXU);

module_param(tcdev_minor,int,S_IRWXU);

static int tcdev_open(struct inode * node,struct file * filep)

{

printk(KERN_INFO "tcdev open\n");

return 0;

}

static ssize_t tcdev_read(struct file *file, char __user *buf, size_t count, loff_t *fops)

{

printk(KERN_INFO "tcdev read\n");

return 0;

}

static ssize_t tcdev_write (struct file *file, char __user *buf, size_t count, loff_t *fops)

{

printk(KERN_INFO "tcdev write\n");

return 0;

}

static int tcdev_release(struct inode * node,struct file * filep)

{

printk(KERN_INFO "tcdev write\n");

return 0;

}

static struct file_operations tcdev_fops = {

.owner=THIS_MODULE,

.open=tcdev_open,

.read=tcdev_read,

.write=tcdev_write,

.release=tcdev_release,

};

static struct cdev tcdev;

static int __init tcdev_init(void)

{

int ret =-EFAULT;

dev_t tcdev_t;

tcdev_t=MKDEV(tcdev_major,tcdev_minor);

printk(KERN_INFO "tcdev start ...\n");

if(TCDEV_MAJOR>0){

ret= alloc_chrdev_region(&tcdev_t,tcdev_minor,TCDEV_NUM,TCDEV_NAME);

if(ret<0){

printk(KERN_ERR"tcdev cdev num apply is fail\n");

goto tcdev_cdev_fail;

}

}

else{

ret=register_chrdev_region(tcdev_t,TCDEV_NUM,TCDEV_NAME);

if(ret<0){

printk(KERN_ERR "tcdev cdev num apply is fail\n");

goto tcdev_cdev_fail;

}

}

printk(KERN_INFO "tcdev cdev num apply is success,dev_t is %d\n",tcdev_t);

memset(&tcdev,0,sizeof(struct cdev));

cdev_init(&tcdev,&tcdev_fops);

ret=cdev_add(&tcdev,tcdev_t,TCDEV_NUM);

if(ret<0){

printk(KERN_ERR"tcdev cdev cdev_add is fail\n");

goto tcdev_cdev_add_fail;

}

printk(KERN_INFO"tcdev cdev_add apply is success\n");

tcdev_cdev_add_fail:

unregister_chrdev_region(&tcdev,TCDEV_NUM);

tcdev_cdev_fail:

return 0;

}

static void __exit tcdev_exit (void)

{

printk(KERN_INFO "tcdev stop ...\n");

cdev_del(&tcdev);

printk(KERN_INFO"tcdev del success\n");

unregister_chrdev_region(&tcdev,TCDEV_NUM);

printk(KERN_INFO "tcdev dev_num del success\n");

return 0;

}

module_init(tcdev_init);

module_exit(tcdev_exit);

时间: 2024-10-18 17:44:59

字符类设备的相关文章

linux驱动开发之misc类设备介绍

1.什么是misc设备? misc是英文的简称,中文名一般叫做杂项设备/杂散设备. 我们知道大部分的设备都有一个明确的分类class,有一些设备进行分类时不太好分,我们不知道一些设备到底应该分到哪一类设备中去,所以最后将这些不知道分到哪类中的设备给分到misc设备中,也就是分到了杂散类中.像蜂鸣器还有ADC设备都被分到了misc设备杂散类设备中.杂散类设备对应的是一个类的概念.随意进到系统中的/sys/class目录中就会看到一个misc目录,这个misc就是杂散类设备,进入到misc目录中,我

字符型设备

在UNIX系统中文件分为四种:1普通文件(ordinary file),分为: (1) 文本文件 (2) 二进制文件2 目录文件(directory) 3 特殊文件(special file),分为: (1)块设备文件(2)字符设备文件 4 符号链接文件(symbolic links) 其中特殊文件也称设备文件,代表着某种设备,一般放在/dev目录下,如/dev/cd0表示光驱.特殊文件分为块设备文件和字符设备文件,块设备文件以区块为输入输出单元,如磁盘:字符设备文件是以字符作为输入输出单元,如

正则表达式中的字符类

字符类引用 [[:alnum:]] 字母和数字 [[:alpha:]] 字母[[:blank:]] 仅表示空格和制表符[[:cntrl:]] 控制字符[[:digit:]] 十进制数[[:graph:]] 打印字符,不包含空格[[:lower:]] 小写字母[[:upper:]] 大写字母[[:print:]] 打印字符,包含空格[[:punct:]] 打印字符,不包含字母和数字[[:space:]] 空格[[:xdigit:]] 十六进制数

JavaScript正则表达式-字符类

JavaScript正则表达式字符类包括六种: 1.字符列表. 2.反向列表. 3.字符范围. 4.反向范围. 5.组合类. 6.预定义类. 字符列表 在方括号内指定一个或者多个字符组成的字符列表,与字符列表中任意字符匹配,都被认为是匹配的.每次匹配只能匹配列表中的一个字符. str = "bird,head,fed,meadow,3d"; reg_pattern = /[rea3s]d/g; arr_m = str.match(reg_pattern);//arr_m = [&quo

linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write【转】

本文转载自:http://blog.chinaunix.net/uid-25014876-id-59417.html linux设备驱动归纳总结(三):2.字符型设备的操作open.close.read.write 一.文件操作结构体file_operations 继续上次没讲完的问题,文件操作结构体到底是什么东西,为什么我注册了设备之后什么现象都没有?可以验证文件操作结构体的内容. file_operations是一个函数指针的集合,用于存放我们定义的用于操作设备的函数的指针,如果我们不定义,

Linux正则表达式-排除字符类

通常,字符类包括在哪个位置想要匹配的所有的字符.在类中作为第一个字符的脱字符(^)将类中的所有字符排除在被匹配之外.相反,除换行符以外的没有列在方括号中的任意字符都将匹配.下面的模式将匹配任意非数字字符: [^0-9] 它匹配字母表中所有的大写和小写字母以及所有特殊字符,例如标点符号.排除特殊字符有时比显示地列出想要匹配的所有字符更方便.例如,如果想要匹配任意辅音,可以简单地排除元音: [^aeiou] 该表达式匹配任意辅音,大写的任意元音,任意标点符合或特殊的字符. 请看下面的正则表达式: \

java正则表达式中的POSIX 字符类和Unicode 块和类别的类介绍

假如现在有一个需求,要你用Java语言来匹配出一个文本里面的所有(英文半角)标点符号,你会怎么写呢?我想大多数人应该是把这些符号都罗列出来, 如: !"#$%&'()*+,-./:;<=>[email protected][\]^_`{|}~ 但[!"#$%&'()*+,-./:;<=>[email protected][\]^_`{|}~]这样写需要转义一下, 结果为: [-!"\#\$%&'()*+,./:;<=>

正则表达式-字符类

字符类是对通配符概念的改进.我们可以列出要匹配的字符,而不是匹配特殊位置的任意字符.使用方括号元字符( [] )将字符列表括起来,其中每个字符占据一个位置. 字符类在处理大写和小写字母时非常有用.例如,如果"what" 可能以首字母大写或小写的形式出现,则可以指定: [Ww]hat 这个正则表达式可以匹配"what" 或"What" .它匹配包含这4个字符的字符串的任意行,第一个字符是"W" 或"w" .因

【黑马程序员】————Foundation框架02常用类—字符类

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 常用类 NSString ->NSMutableString NSArray ->NSMutableArray NSSet ->NSMutableSet NSDictionary ->NSMutableDictionary NSDate NSObject 字符类-NSString/NSMutableString NSString : 不可变字符串  NSMutableString