<4D F736F F D20B5DA36D5C22020D7D6B7FBC9E8B1B8C7FDB6AF>

Size: px
Start display at page:

Download "<4D F736F F D20B5DA36D5C22020D7D6B7FBC9E8B1B8C7FDB6AF>"

Transcription

1 LINUX 设备驱动开发详解 作者 : 华清远见 第 6 章 字符设备驱动 Linux Linux 6.1 Linux cdev file_operations Linux 6.2 globalmem globalmem seek() I/O globalmem globalmem

2 Linux 字符设备驱动结构 cdev 结构体 在 Linux 2.6 内核中使用 cdev 结构体描述字符设备,cdev 结构体的定义如代码清单 6.1 所示 代码清单 6.1 cdev 结构体 1 struct cdev 2 { 3 struct kobject kobj; /* 内嵌的 kobject 对象 */ 4 struct module *owner; /* 所属模块 */ 5 struct file_operations *ops; /* 文件操作结构体 */ 6 struct list_head list; 7 dev_t dev; /* 设备号 */ 8 unsigned int count; 9 }; cdev 结构体的 dev_t 成员定义了设备号, 为 32 位, 其中高 12 位为主设备号, 低 20 位为次设备号 使用下列宏可以从 dev_t 获得主设备号和次设备号 MAJOR(dev_t dev) MINOR(dev_t dev) 而使用下列宏则可以通过主设备号和设备号生成 dev_t MKDEV(int major, int minor) cdev 结构体的另一个重要成员 file_operations 定义了字符设备驱动提供给虚拟文件系统的接口函数 Linux 2.6 内核提供了一组函数用于操作 cdev 结构体, 如下所示 : void cdev_init(struct cdev *, struct file_operations *); struct cdev *cdev_alloc(void); void cdev_put(struct cdev *p); int cdev_add(struct cdev *, dev_t, unsigned); void cdev_del(struct cdev *); cdev_init() 函数用于初始化 cdev 的成员, 并建立 cdev 和 file_operations 之间的连接, 其源代码如代码清单 6.2 所示 代码清单 6.2 cdev_init() 函数 1 void cdev_init(struct cdev *cdev, struct file_operations *fops) 2 { 3 memset(cdev, 0, sizeof *cdev); 4 INIT_LIST_HEAD(&cdev->list); 5 cdev->kobj.ktype = &ktype_cdev_default; 6 kobject_init(&cdev->kobj); 7 cdev->ops = fops; /* 将传入的文件操作结构体指针赋值给 cdev 的 ops*/ 8 } cdev_alloc() 函数用于动态申请一个 cdev 内存, 其源代码如代码清单 6.3 所示 2

3 代码清单 6.3 cdev_alloc() 函数 专业始于专注卓识源于远见 1 struct cdev *cdev_alloc(void) 2 { 3 struct cdev *p=kmalloc(sizeof(struct cdev),gfp_kernel); /* 分配 cdev 的内存 */ 4 if (p) { 5 memset(p, 0, sizeof(struct cdev)); 6 p->kobj.ktype = &ktype_cdev_dynamic; 7 INIT_LIST_HEAD(&p->list); 8 kobject_init(&p->kobj); 9 } 10 return p; 11 } cdev_add() 函数和 cdev_del() 函数分别向系统添加和删除一个 cdev, 完成字符设备的注册和注销 对 cdev_add() 的调用通常发生在字符设备驱动模块加载函数中, 而对 cdev_del() 函数的调用则通常发生在字符设备驱动模块卸载函数中 分配和释放设备号 在调用 cdev_add() 函数向系统注册字符设备之前, 应首先调用 register_chrdev_region() 或 alloc_chrdev_region() 函数向系统申请设备号, 这两个函数的原型如下 : int register_chrdev_region(dev_t from, unsigned count, const char *name); int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name); register_chrdev_region() 函数用于已知起始设备的设备号的情况 ; 而 alloc_chrdev_region() 用于设备号未知, 向系统动态申请未被占用的设备号的情况 函数调用成功之后, 会把得到的设备号放入第一个参数 dev 中 alloc_chrdev_region() 与 register_chrdev_region() 对比的优点在于它会自动避开设备号重复的冲突 相反地, 在调用 cdev_del() 函数从系统注销字符设备之后,unregister_chrdev_region() 应该被调用以释放原先申请的设备号, 这个函数的原型如下 : void unregister_chrdev_region(dev_t from, unsigned count); file_operations 结构体 file_operations 结构体中的成员函数是字符设备驱动程序设计的主体内容, 这些函数实际会在应用程序进行 Linux 的 open() write() read() close() 等系统调用时最终被调用 file_operations 结构体目前已经比较庞大, 它的定义如代码清单 6.4 所示 代码清单 6.4 file_operations 结构体 1 struct file_operations 2 { 3 struct module *owner; 4 // 拥有该结构的模块的指针, 一般为 THIS_MODULES 5 loff_t(*llseek)(struct file *, loff_t, int); 6 // 用来修改文件当前的读写位置 7 ssize_t(*read)(struct file *, char user *, size_t, loff_t*); 8 // 从设备中同步读取数据 9 ssize_t(*aio_read)(struct kiocb *, char user *, size_t, loff_t); 10 // 初始化一个异步的读取操作 11 ssize_t(*write)(struct file *, const char user *, size_t, loff_t*); 12 // 向设备发送数据 13 ssize_t(*aio_write)(struct kiocb *, const char user *, size_t, loff_t); 14 // 初始化一个异步的写入操作 15 int(*readdir)(struct file *, void *, filldir_t); 16 // 仅用于读取目录, 对于设备文件, 该字段为 NULL 17 unsigned int(*poll)(struct file *, struct poll_table_struct*); 18 // 轮询函数, 判断目前是否可以进行非阻塞的读取或写入 19 int(*ioctl)(struct inode *, struct file *, unsigned int, unsigned long); 20 // 执行设备 I/O 控制命令 21 long(*unlocked_ioctl)(struct file *, unsigned int, unsigned long); 22 // 不使用 BLK 文件系统, 将使用此种函数指针代替 ioctl 23 long(*compat_ioctl)(struct file *, unsigned int, unsigned long); 24 // 在 64 位系统上,32 位的 ioctl 调用将使用此函数指针代替 3

4 25 int(*mmap)(struct file *, struct vm_area_struct*); 26 // 用于请求将设备内存映射到进程地址空间 27 int(*open)(struct inode *, struct file*); 28 // 打开 29 int(*flush)(struct file*); 30 int(*release)(struct inode *, struct file*); 31 // 关闭 32 int(*synch)(struct file *, struct dentry *, int datasync); 33 // 刷新待处理的数据 34 int(*aio_fsync)(struct kiocb *, int datasync); 35 // 异步 fsync 36 int(*fasync)(int, struct file *, int); 37 // 通知设备 FASYNC 标志发生变化 38 int(*lock)(struct file *, int, struct file_lock*); 39 ssize_t(*readv)(struct file *, const struct iovec *, unsigned long, loff_t*); 40 ssize_t(*writev)(struct file *, const struct iovec *, unsigned long, loff_t*); 41 // readv 和 writev: 分散 / 聚集型的读写操作 42 ssize_t(*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void*); 43 // 通常为 NULL 44 ssize_t(*sendpage)(struct file *, struct page *, int, size_t, loff_t *, int); 45 // 通常为 NULL 46 unsigned long(*get_unmapped_area)(struct file *,unsigned long, unsigned long, 47 unsigned long, unsigned long); 48 // 在进程地址空间找到一个将底层设备中的内存段映射的位置 49 int(*check_flags)(int); 50 // 允许模块检查传递给 fcntl(f_setel...) 调用的标志 51 int(*dir_notify)(struct file *filp, unsigned long arg); 52 // 仅对文件系统有效, 驱动程序不必实现 53 int(*flock)(struct file *, int, struct file_lock*); 54 }; 下面对 file_operations 结构体中的主要成员进行讲解 llseek() 函数用来修改一个文件的当前读写位置, 并将新位置返回, 在出错时, 这个函数返回一个负值 read() 函数用来从设备中读取数据, 成功时函数返回读取的字节数, 出错时返回一个负值 write() 函数向设备发送数据, 成功时该函数返回写入的字节数 如果此函数未被实现, 当用户进行 write() 系统调用时, 将得到 -EINVAL 返回值 readdir() 函数仅用于目录, 设备节点不需要实现它 ioctl() 提供设备相关控制命令的实现 ( 既不是读操作也不是写操作 ), 当调用成功时, 返回给调用程序一 个非负值 内核本身识别部分控制命令, 而不必调用设备驱动中的 ioctl() 如果设备不提供 ioctl() 函数, 对 于内核不能识别的命令, 用户进行 ioctl() 系统调用时将获得 -EINVAL 返回值 mmap() 函数将设备内存映射到进程内存中, 如果设备驱动未实现此函数, 用户进行 mmap() 系统调用 时将获得 -ENODEV 返回值 这个函数对于帧缓冲等设备特别有意义 当用户空间调用 Linux API 函数 open() 打开设备文件时, 设备驱动的 open() 函数最终被调用 驱动程序 可以不实现这个函数, 在这种情况下, 设备的打开操作永远成功 与 open() 函数对应的是 release() 函数 poll() 函数一般用于询问设备是否可被非阻塞地立即读写 当询问的条件未触发时, 用户空间进行 select() 和 poll() 系统调用将引起进程的阻塞 aio_read() 和 aio_write() 函数分别对与文件描述符对应的设备进行异步读 写操作 设备实现这两个函数 后, 用户空间可以对该设备文件描述符调用 aio_read() aio_write() 等系统调用进行读写 Linux 字符设备驱动的组成 在 Linux 系统中, 字符设备驱动由如下几个部分组成 1. 字符设备驱动模块加载与卸载函数 在字符设备驱动模块加载函数中应该实现设备号的申请和 cdev 的注册, 而在卸载函数中应实现设备号的释放和 cdev 的注销 工程师通常习惯将设备定义为一个设备相关的结构体, 其包含该设备所涉及的 cdev 私有数据及信号 4

5 量等信息 常见的设备结构体 模块加载和卸载函数形式如代码清单 6.5 所示 代码清单 6.5 字符设备驱动模块加载与卸载函数模板 1 // 设备结构体 2 struct xxx_dev_t 3 { 4 struct cdev cdev; } xxx_dev; 7 // 设备驱动模块加载函数 8 static int init xxx_init(void) 9 { cdev_init(&xxx_dev.cdev, &xxx_fops); // 初始化 cdev 12 xxx_dev.cdev.owner = THIS_MODULE; 13 // 获取字符设备号 14 if (xxx_major) 15 { 16 register_chrdev_region(xxx_dev_no, 1, DEV_NAME); 17 } 18 else 19 { 20 alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME); 21 } ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1); // 注册设备 } 26 /* 设备驱动模块卸载函数 */ 27 static void exit xxx_exit(void) 28 { 29 unregister_chrdev_region(xxx_dev_no, 1); // 释放占用的设备号 30 cdev_del(&xxx_dev.cdev); // 注销设备 } 专业始于专注卓识源于远见 2. 字符设备驱动的 file_operations 结构体中成员函数 file_operations 结构体中成员函数是字符设备驱动与内核的接口, 是用户空间对 Linux 进行系统调用最终的落实者 大多数字符设备驱动会实现 read() write() 和 ioctl() 函数, 常见的字符设备驱动的这 3 个函数的形式如代码清单 6.6 所示 代码清单 6.6 字符设备驱动读 写 I/O 控制函数模板 1 /* 读设备 */ 2 ssize_t xxx_read(struct file *filp, char user *buf, size_t count, 3 loff_t*f_pos) 4 { copy_to_user(buf,...,...); } 9 /* 写设备 */ 10 ssize_t xxx_write(struct file *filp, const char user *buf, size_t count, 11 loff_t *f_pos) 12 { copy_from_user(..., buf,...); } 17 /* ioctl 函数 */ 18 int xxx_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 19 unsigned long arg) 20 {

6 22 switch (cmd) 23 { 24 case XXX_CMD1: break; 27 case XXX_CMD2: break; 30 default: 31 /* 不能支持的命令 */ 32 return - ENOTTY; 33 } 34 return 0; 35 } 设备驱动的读函数中,filp 是文件结构体指针,buf 是用户空间内存的地址, 该地址在内核空间不能直接读写,count 是要读的字节数,f_pos 是读的位置相对于文件开头的偏移 设备驱动的写函数中,filp 是文件结构体指针,buf 是用户空间内存的地址, 该地址在内核空间不能直接读写,count 是要写的字节数,f_pos 是写的位置相对于文件开头的偏移 由于内核空间与用户空间的内存不能直接互访, 因此借助函数 copy_from_user() 完成用户空间到内核空间的复制, 函数 copy_to_user() 完成内核空间到用户空间的复制 copy_from_user() 和 copy_to_user() 的原型如下所示 : unsigned long copy_from_user(void *to, const void user *from, unsigned long count); unsigned long copy_to_user(void user *to, const void *from, unsigned long count); 上述函数均返回不能被复制的字节数, 因此, 如果完全复制成功, 返回值为 0 如果要复制的内存是简单类型, 如 char int long 等, 则可以使用简单的 put_user() 和 get_user(), 如下所示 : int val; // 内核空间整型变量... get_user(val, (int *) arg); // 用户空间到内核空间,arg 是用户空间的地址... put_user(val, (int *) arg); // 内核空间到用户空间,arg 是用户空间的地址读和写函数中的 user 是一个宏, 表明其后的指针指向用户空间, 这个宏定义如下 : #ifdef CHECKER # define user attribute ((noderef, address_space(1))) #else # define user #endif I/O 控制函数的 cmd 参数为事先定义的 I/O 控制命令, 而 arg 为对应于该命令的参数 例如对于串行设备, 如果 SET_BAUDRATE 是一个设置波特率的命令, 那后面的 arg 就应该是波特率值 在字符设备驱动中, 需要定义一个 file_operations 的实例, 并将具体设备驱动的函数赋值给 file_operations 的成员, 如代码清单 6.7 所示 代码清单 6.7 字符设备驱动文件操作结构体模板 1 struct file_operations xxx_fops = 2 { 3.owner = THIS_MODULE, 4.read = xxx_read, 5.write = xxx_write, 6.ioctl = xxx_ioctl, }; 上述 xxx_fops 在代码清单 6.5 第 11 行的 cdev_init(&xxx_dev.cdev, &xxx_fops) 的语句中被建立与 cdev 的连接 图 6.1 所示为字符设备驱动的结构 字符设备驱动与字符设备以及字符设备驱动与用户空间访问该设备的程序之间的关系 6

7 globalmem 虚拟设备实例描述 从本章开始, 后续的几章都将基于虚拟的 globalmem 设备进行字符设备驱动的讲解 globalmem 意味着 全局内存, 在 globalmem 字符设备驱动中会分配一片大小为 GLOBALMEM_ SIZE(4KB) 的内存空间, 并在驱动中提供针对该片内存的读写 控制和定位函数, 以供用户空间的进程能通过 Linux 系统调用访问这片内存 本章将给出 globalmem 设备驱动的雏形, 而后续章节会在这个雏形的基础上添加并发与同步控制等复杂功能 1.5 globalmem 设备驱动 头文件 宏及设备结构体 在 globalmem 字符设备驱动中, 应包含它要使用的头文件, 并定义 globalmem 设备结构体及相关宏 代码清单 6.8 globalmem 设备结构体和宏 1 #include <linux/module.h> 2 #include <linux/types.h> 3 #include <linux/fs.h> 4 #include <linux/errno.h> 5 #include <linux/mm.h> 6 #include <linux/sched.h> 7 #include <linux/init.h> 8 #include <linux/cdev.h> 9 #include <asm/io.h> 10 #include <asm/system.h> 11 #include <asm/uaccess.h> #define GLOBALMEM_SIZE 0x1000 /* 全局内存大小 :4KB*/ 14 #define MEM_CLEAR 0x1 /* 清零全局内存 */ 7

8 15 #define GLOBALMEM_MAJOR 254 /* 预设的 globalmem 的主设备号 */ static globalmem_major = GLOBALMEM_MAJOR; 18 /*globalmem 设备结构体 */ 19 struct globalmem_dev 20 { 21 struct cdev cdev; /*cdev 结构体 */ 22 unsigned char mem[globalmem_size]; /* 全局内存 */ 23 }; struct globalmem_dev dev; /* 设备结构体实例 */ 专业始于专注卓识源于远见 从第 19~23 行代码可以看出, 定义的 globalmem_dev 设备结构体包含了对应于 globalmem 字符设备的 cdev 使用的内存 mem[globalmem_size] 当然, 程序中并不一定要把 mem[globa- LMEM_SIZE] 和 cdev 包含在一个设备结构体中, 但这样定义的好处在于它借用了面向对象程序设计中 封装 的思想, 体现了一种良好的编程习惯 加载与卸载设备驱动 globalmem 设备驱动的模块加载和卸载函数遵循代码清单 6.5 的类似模板, 其实现的功能与代码清单 6.5 完全一致, 如代码清单 6.9 所示 代码清单 6.9 globalmem 设备驱动模块加载与卸载函数 1 /*globalmem 设备驱动模块加载函数 */ 2 int globalmem_init(void) 3 { 4 int result; 5 dev_t devno = MKDEV(globalmem_major, 0); 6 7 /* 申请字符设备驱动区域 */ 8 if (globalmem_major) 9 result = register_chrdev_region(devno, 1, "globalmem"); 10 else 11 /* 动态获得主设备号 */ 12 { 13 result = alloc_chrdev_region(&devno, 0, 1, "globalmem"); 14 globalmem_major = MAJOR(devno); 15 } 16 if (result < 0) 17 return result; globalmem_setup_cdev(); 20 return 0; 21 } /*globalmem 设备驱动模块卸载函数 */ 24 void globalmem_exit(void) 25 { 26 cdev_del(&dev.cdev); /* 删除 cdev 结构 */ 27 unregister_chrdev_region(mkdev(globalmem_major, 0), 1);/* 注销设备区域 */ 28 } 第 19 行调用的 globalmem_setup_cdev() 函数完成 cdev 的初始化和添加, 如代码清单 6.10 所示 代码清单 6.10 初始化并添加 cdev 结构体 1 /* 初始化并添加 cdev 结构体 */ 2 static void globalmem_setup_cdev() 3 { 4 int err, devno = MKDEV(globalmem_major, 0); 5 6 cdev_init(&dev.cdev, &globalmem_fops); 7 dev.cdev.owner = THIS_MODULE; 8

9 8 dev.cdev.ops = &globalmem_fops; 9 err = cdev_add(&dev.cdev, devno, 1); 10 if (err) 11 printk(kern_notice "Error %d adding globalmem", err); 12 } 专业始于专注卓识源于远见 在 cdev_init() 函数中, 与 globalmem 的 cdev 关联的 file_operations 结构体如代码清单 6.11 所示 代码清单 6.11 globalmem 设备驱动文件操作结构体 1 static const struct file_operations globalmem_fops = 2 { 3.owner = THIS_MODULE, 4.llseek = globalmem_llseek, 5.read = globalmem_read, 6.write = globalmem_write, 7.ioctl = globalmem_ioctl, 8 }; 读写函数 globalmem 设备驱动的读写函数主要是让设备结构体的 mem[] 数组与用户空间交互数据, 并随着访问的字节数变更返回用户的文件读写偏移位置 读和写函数的实现分别如代码清单 6.12 和代码清单 6.13 所示 代码清单 6.12 globalmem 设备驱动的读函数 1 static ssize_t globalmem_read(struct file *filp, char user *buf, size_t count, 2 loff_t *ppos) 3 { 4 unsigned long p = *ppos; 5 int ret = 0; 6 7 /* 分析和获取有效的读长度 */ 8 if (p >= GLOBALMEM_SIZE) // 要读的偏移位置越界 9 return count? - ENXIO: 0; 10 if (count > GLOBALMEM_SIZE - p)// 要读的字节数太大 11 count = GLOBALMEM_SIZE - p; /* 内核空间 用户空间 */ 14 if (copy_to_user(buf, (void*)(dev.mem + p), count)) 15 { 16 ret = - EFAULT; 17 } 18 else 19 { 20 *ppos += count; 21 ret = count; printk(kern_info "read %d bytes(s) from %d\n", count, p); 24 } return ret; 9

10 27 } 代码清单 6.13 globalmem 设备驱动的写函数 1 static ssize_t globalmem_write(struct file *filp, const char user *buf, 2 size_t count, loff_t *ppos) 3 { 4 unsigned long p = *ppos; 5 int ret = 0; 6 7 /* 分析和获取有效的写长度 */ 8 if (p >= GLOBALMEM_SIZE) // 要写的偏移位置越界 9 return count? - ENXIO: 0; 10 if (count > GLOBALMEM_SIZE - p) // 要写的字节数太多 11 count = GLOBALMEM_SIZE - p; /* 用户空间 内核空间 */ 14 if (copy_from_user(dev->mem + p, buf, count)) 15 ret = - EFAULT; 16 else 17 { 18 *ppos += count; 19 ret = count; printk(kern_info "written %d bytes(s) from %d\n", count, p); 22 } return ret; 25 } seek() 函数 seek() 函数对文件定位的起始地址可以是文件开头 (SEEK_SET,0) 当前位置(SEEK_CUR,1) 和 文件尾 (SEEK_END,2),globalmem 支持从文件开头和当前位置相对偏移 在定位的时候, 应该检查用户请求的合法性, 若不合法, 函数返回 - EINVAL, 合法时返回文件的当前 位置, 如代码清单 6.14 所示 代码清单 6.14 globalmem 设备驱动的 seek() 函数 1 static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig) 2 { 3 loff_t ret; 4 switch (orig) 5 { 6 case 0: /* 从文件开头开始偏移 */ 7 if (offset < 0) 8 { 9 ret = - EINVAL; 10 break; 11 } 12 if ((unsigned int)offset > GLOBALMEM_SIZE) // 偏移越界 10

11 13 { 14 ret = - EINVAL; 15 break; 16 } 17 filp->f_pos = (unsigned int)offset; 18 ret = filp->f_pos; 19 break; 20 case 1: /* 从当前位置开始偏移 */ 21 if ((filp->f_pos + offset) > GLOBALMEM_SIZE) // 偏移越界 22 { 23 ret = - EINVAL; 24 break; 25 } 26 if ((filp->f_pos + offset) < 0) 27 { 28 ret = - EINVAL; 29 break; 30 } 31 filp->f_pos += offset; 32 ret = filp->f_pos; 33 break; 34 default: 35 ret = - EINVAL; 36 } 37 return ret; 38 } ioctl() 函数 1.globalmem 设备驱动的 ioctl() 函数 globalmem 设备驱动的 ioctl() 函数接受 MEM_CLEAR 命令, 这个命令会将全局内存的有效数据长度清零, 对于设备不支持的命令,ioctl() 函数应该返回 -EINVAL, 如代码清单 6.15 所示 代码清单 6.15 globalmem 设备驱动的 ioctl() 函数 1 static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned 2 int cmd, unsigned long arg) 3 { 4 switch (cmd) 5 { 6 case MEM_CLEAR: 7 // 清除全局内存 8 memset(dev->mem, 0, GLOBALMEM_SIZE); 9 printk(kern_info "globalmem is set to zero\n"); 10 break; default: 13 return - EINVAL; // 其他不支持的命令 14 } 15 return 0; 16 } 在上述程序中,MEM_CLEAR 被宏定义为 0x01, 实际上并不是一种值得推荐的方法, 简单地对命令定义为 11

12 0x0 0x1 0x2 等类似值会导致不同的设备驱动拥有相同的命令号 如果设备 A B 都支持 0x0 0x1 0x2 这样的命令, 假设用户本身希望给 A 发 0x1 命令, 可是不经意间发给了 B, 这个时候 B 因为支持该命令, 它就会执行该命令 因此,Linux 内核推荐采用一套统一的 ioctl() 命令生成方式 2.ioctl() 命令 Linux 系统建议以如图 6.2 所示的方式定义 ioctl() 的命令码 设备类型序列号方向数据尺寸 8bit 8bit 2bit 13/14bit 6.2 ioctl() 命令码的设备类型字段为一个 幻数, 可以是 0~0xff 之间的值, 内核中的 ioctl-number.txt 给出了一些推荐的和已经被使用的 幻数, 新设备驱动定义 幻数 的时候要避免与其冲突 命令码的序列号也是 8 位宽 命令码的方向字段为 2 位, 该字段表示数据传送的方向, 可能的值是 _IOC_NONE( 无数据传输 ) _IOC_READ( 读 ) _IOC_WRITE( 写 ) 和 _IOC_READ _IOC_WRITE( 双向 ) 数据传送的方向是从应用程序的角度来看的 命令码的数据长度字段表示涉及的用户数据的大小, 这个成员的宽度依赖于体系结构, 通常是 13 位或者 14 位 内核还定义了 _IO() _IOR() _IOW() 和 _IOWR() 这 4 个宏来辅助生成命令, 这 4 个宏的通用定义如代码清单 6.16 所示 代码清单 6.16 _IO() _IOR() _IOW() 和 _IOWR() 宏定义 1 #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) 2 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),\ 3 (_IOC_TYPECHECK(size))) 4 #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),\ 5 (_IOC_TYPECHECK(size))) 6 #define _IOWR(type,nr,size) _IOC(_IOC_READ _IOC_WRITE,(type),(nr), \ 7 (_IOC_TYPECHECK(size))) 8 /*_IO _IOR 等使用的 _IOC 宏 */ 9 #define _IOC(dir,type,nr,size) \ 10 (((dir) << _IOC_DIRSHIFT) \ 11 ((type) << _IOC_TYPESHIFT) \ 12 ((nr) << _IOC_NRSHIFT) \ 13 ((size) << _IOC_SIZESHIFT)) 由此可见, 这几个宏的作用是根据传入的 type( 设备类型字段 ) nr( 序列号字段 ) 和 size( 数据长度 字段 ) 和宏名隐含的方向字段移位组合生成命令码 由于 globalmem 的 MEM_CLEAR 命令不涉及数据传输, 因此它可以定义如下 : #define GLOBALMEM_MAGIC #define MEM_CLEAR _IO(GLOBALMEM_MAGIC,0) 3. 预定义命令 内核中预定义了一些 I/O 控制命令, 如果某设备驱动中包含了与预定义命令一样的命令, 这些命令会被当作预定义命令被内核处理而不是被设备驱动处理, 预定义命令有如下 4 种 FIOCLEX: 即 File IOctl Close on Exec, 对文件设置专用标志, 通知内核当 exec() 系统调用发生时自动关闭打开的文件 FIONCLEX: 即 File IOctl Not CLose on Exec, 与 FIOCLEX 标志相反, 清除由 FIOCLEX 命令设置的标志 12

13 FIOQSIZE: 获得一个文件或者目录的大小, 当用于设备文件时, 返回一个 ENOTTY 错误 FIONBIO: 即 File IOctl Non-Blocking I/O, 这个调用修改在 filp->f_flags 中的 O_NONBLOCK 标志 FIOCLEX FIONCLEX FIOQSIZE 和 FIONBIO 这些宏的定义如下 : #define FIONCLEX 0x5450 #define FIOCLEX 0x5451 #define FIOQSIZE 0x5460 #define FIONBIO 0x5421 由以上定义可以看出,FIOCLEX FIONCLEX FIOQSIZE 和 FIONBIO 的幻数为 T 使用文件私有数据 6.3.1~6.3.5 节给出的代码完整地实现了预期的 globalmem 雏形, 在其代码中, 为 globalmem 设备结构体 globalmem_dev 定义了全局实例 dev( 见代码清单 6.8 第 25 行 ), 而 globalmem 的驱动中 read() write() ioctl() llseek() 函数都针对 dev 进行操作 实际上, 大多数 Linux 驱动工程师都将文件的私有数据 private_data 指向设备结构体,read() write() ioctl() llseek() 等函数通过 private_data 访问设备结构体 下面对各函数进行少量的修改, 使读者了解字符设备驱动的全貌, 代码清单 6.17 列出了完整的使用文件私有数据的 globalmem 的设备驱动 代码清单 6.17 使用文件私有数据的 globalmem 的设备驱动 1 #include <linux/module.h> 2 #include <linux/types.h> 3 #include <linux/fs.h> 4 #include <linux/errno.h> 5 #include <linux/mm.h> 6 #include <linux/sched.h> 7 #include <linux/init.h> 8 #include <linux/cdev.h> 9 #include <asm/io.h> 10 #include <asm/system.h> 11 #include <asm/uaccess.h> #define GLOBALMEM_SIZE 0x1000 /* 全局内存最大 4KB*/ 14 #define MEM_CLEAR 0x1 /* 清零全局内存 */ 15 #define GLOBALMEM_MAJOR 254 /* 预设的 globalmem 的主设备号 */ static globalmem_major = GLOBALMEM_MAJOR; 18 /*globalmem 设备结构体 */ 19 struct globalmem_dev 20 { 21 struct cdev cdev; /*cdev 结构体 */ 22 unsigned char mem[globalmem_size]; /* 全局内存 */ 23 }; struct globalmem_dev *globalmem_devp; /* 设备结构体指针 */ 26 /* 文件打开函数 */ 27 int globalmem_open(struct inode *inode, struct file *filp) 28 { 13

14 29 /* 将设备结构体指针赋值给文件私有数据指针 */ 30 filp->private_data = globalmem_devp; 31 return 0; 32 } 33 /* 文件释放函数 */ 34 int globalmem_release(struct inode *inode, struct file *filp) 35 { 36 return 0; 37 } /* ioctl 设备控制函数 */ 40 static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned 41 int cmd, unsigned long arg) 42 { 43 struct globalmem_dev *dev = filp->private_data;/* 获得设备结构体指针 */ switch (cmd) 46 { 47 case MEM_CLEAR: 48 memset(dev->mem, 0, GLOBALMEM_SIZE); 49 printk(kern_info "globalmem is set to zero\n"); 50 break; default: 53 return - EINVAL; 54 } 55 return 0; 56 } /* 读函数 */ 59 static ssize_t globalmem_read(struct file *filp, char user *buf, size_t size, 60 loff_t *ppos) 61 { 62 unsigned long p = *ppos; 63 unsigned int count = size; 64 int ret = 0; 65 struct globalmem_dev *dev = filp->private_data; /* 获得设备结构体指针 */ /* 分析和获取有效的写长度 */ 68 if (p >= GLOBALMEM_SIZE) 69 return count? - ENXIO: 0; 70 if (count > GLOBALMEM_SIZE - p) 71 count = GLOBALMEM_SIZE - p; /* 内核空间 用户空间 */ 74 if (copy_to_user(buf, (void*)(dev->mem + p), count)) 75 { 14

15 76 ret = - EFAULT; 77 } 78 else 79 { 80 *ppos += count; 81 ret = count; printk(kern_info "read %d bytes(s) from %d\n", count, p); 84 } return ret; 87 } /* 写函数 */ 90 static ssize_t globalmem_write(struct file *filp, const char user *buf, 91 size_t size, loff_t *ppos) 92 { 93 unsigned long p = *ppos; 94 unsigned int count = size; 95 int ret = 0; 96 struct globalmem_dev *dev = filp->private_data; /* 获得设备结构体指针 */ /* 分析和获取有效的写长度 */ 99 if (p >= GLOBALMEM_SIZE) 100 return count? - ENXIO: 0; 101 if (count > GLOBALMEM_SIZE - p) 102 count = GLOBALMEM_SIZE - p; /* 用户空间 内核空间 */ 105 if (copy_from_user(dev->mem + p, buf, count)) 106 ret = - EFAULT; 107 else 108 { 109 *ppos += count; 110 ret = count; printk(kern_info "written %d bytes(s) from %d\n", count, p); 113 } return ret; 116 } /* seek 文件定位函数 */ 119 static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig) 120 { 121 loff_t ret = 0; 122 switch (orig) 15

16 123 { 124 case 0: /* 相对文件开始位置偏移 */ 125 if (offset < 0) 126 { 127 ret = - EINVAL; 128 break; 129 } 130 if ((unsigned int)offset > GLOBALMEM_SIZE) 131 { 132 ret = - EINVAL; 133 break; 134 } 135 filp->f_pos = (unsigned int)offset; 136 ret = filp->f_pos; 137 break; 138 case 1: /* 相对文件当前位置偏移 */ 139 if ((filp->f_pos + offset) > GLOBALMEM_SIZE) 140 { 141 ret = - EINVAL; 142 break; 143 } 144 if ((filp->f_pos + offset) < 0) 145 { 146 ret = - EINVAL; 147 break; 148 } 149 filp->f_pos += offset; 150 ret = filp->f_pos; 151 break; 152 default: 153 ret = - EINVAL; 154 break; 155 } 156 return ret; 157 } /* 文件操作结构体 */ 160 static const struct file_operations globalmem_fops = 161 { 162.owner = THIS_MODULE, 163.llseek = globalmem_llseek, 164.read = globalmem_read, 165.write = globalmem_write, 166.ioctl = globalmem_ioctl, 167.open = globalmem_open, 168.release = globalmem_release, 169 }; 专业始于专注卓识源于远见 16

17 /* 初始化并注册 cdev*/ 172 static void globalmem_setup_cdev(struct globalmem_dev *dev, int index) 173 { 174 int err, devno = MKDEV(globalmem_major, index); cdev_init(&dev->cdev, &globalmem_fops); 177 dev->cdev.owner = THIS_MODULE; 178 dev->cdev.ops = &globalmem_fops; 179 err = cdev_add(&dev->cdev, devno, 1); 180 if (err) 181 printk(kern_notice "Error %d adding LED%d", err, index); 182 } /* 设备驱动模块加载函数 */ 185 int globalmem_init(void) 186 { 187 int result; 188 dev_t devno = MKDEV(globalmem_major, 0); /* 申请设备号 */ 191 if (globalmem_major) 192 result = register_chrdev_region(devno, 1, "globalmem"); 193 else /* 动态申请设备号 */ 194 { 195 result = alloc_chrdev_region(&devno, 0, 1, "globalmem"); 196 globalmem_major = MAJOR(devno); 197 } 198 if (result < 0) 199 return result; /* 动态申请设备结构体的内存 */ 202 globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL); 203 if (!globalmem_devp) /* 申请失败 */ 204 { 205 result = - ENOMEM; 206 goto fail_malloc; 207 } 208 memset(globalmem_devp, 0, sizeof(struct globalmem_dev)); globalmem_setup_cdev(globalmem_devp, 0); 211 return 0; fail_malloc: unregister_chrdev_region(devno, 1); 214 return result; 215 } /* 模块卸载函数 */ 218 void globalmem_exit(void) 219 { 220 cdev_del(&globalmem_devp->cdev); /* 注销 cdev*/ 221 kfree(globalmem_devp); /* 释放设备结构体内存 */ 222 unregister_chrdev_region(mkdev(globalmem_major, 0), 1); /* 释放设备号 */ 17

18 223 } MODULE_AUTHOR("Song Baohua"); 226 MODULE_LICENSE("Dual BSD/GPL"); module_param(globalmem_major, int, S_IRUGO); module_init(globalmem_init); 231 module_exit(globalmem_exit); 除了在 globalmem_open() 函数中通过 filp->private_data = globalmem_devp 语句 ( 见第 31 行 ) 将设备结构体指针赋值给文件私有数据指针并在 globalmem_read() globalmem_write() globalmem_llseek() 和 globalmem_ioctl() 函数中通过 struct globalmem_dev *dev = filp->private_data 语句获得设备结构体指针并使用该指针操作设备结构体外, 代码清单 6.17 与代码清单 6.8~ 代码清单 6.15 的程序基本相同 现在翻回到本书的第 1 章, 再次阅读代码清单 1.4, 即 Linux 下 LED 的设备驱动, 是否豁然开朗? 代码清单 6.17 仅仅作为使用 private_data 的范例, 直接访问全局变量 globalmem_devp 会更加结构清晰 如果 globalmem 不只包括一个设备, 而是同时包括两个或两个以上的设备, 采用 private_data 的优势就会显现出来 在不对代码清单 6.17 中的 globalmem_read() globalmem_write() globalmem_ioctl() 等重要函数及 globalmem_fops 结构体等数据结构进行任何修改的前提下, 只是简单地修改 globalmem_ init() globalmem_exit() 和 globalmem_open(), 就可以轻松地让 globalmem 驱动中包含两个同样的设备 ( 次设备号分别为 0 和 1), 如代码清单 6.18 所示 代码清单 6.18 支持两个 globalmem 设备的 globalmem 驱动 1 /* 文件打开函数 */ 2 int globalmem_open(struct inode *inode, struct file *filp) 3 { 4 /* 将设备结构体指针赋值给文件私有数据指针 */ 5 struct globalmem_dev *dev; 6 7 dev = container_of(inode->i_cdev,struct globalmem_dev,cdev); 8 filp->private_data = dev; 9 return 0; 10 } /* 设备驱动模块加载函数 */ 13 int globalmem_init(void) 14 { 15 int result; 16 dev_t devno = MKDEV(globalmem_major, 0); /* 申请设备号 */ 19 if (globalmem_major) 20 result = register_chrdev_region(devno, 2, "globalmem"); 21 else /* 动态申请设备号 */ 22 { 23 result = alloc_chrdev_region(&devno, 0, 2, "globalmem"); 24 globalmem_major = MAJOR(devno); 25 } 26 if (result < 0) 27 return result; /* 动态申请两个设备结构体的内存 */ 30 globalmem_devp = kmalloc(2*sizeof(struct globalmem_dev), GFP_KERNEL); 31 if (!globalmem_devp) /* 申请失败 */ 32 { 33 result = - ENOMEM; 34 goto fail_malloc; 35 } 36 memset(globalmem_devp, 0, 2*sizeof(struct globalmem_dev)); 18

19 37 38 globalmem_setup_cdev(globalmem_devp[0], 0); 39 globalmem_setup_cdev(&globalmem_devp[1], 1); 40 return 0; fail_malloc: unregister_chrdev_region(devno, 1); 43 return result; 44 } /* 模块卸载函数 */ 47 void globalmem_exit(void) 48 { 49 cdev_del(&(global mem_devp[0].cdev)); 50 cdev_del(&(global mem_devp[1].cdev)); /* 注销 cdev*/ 51 kfree(globalmem_devp); /* 释放设备结构体内存 */ 52 unregister_chrdev_region(mkdev(globalmem_major, 0), 2); /* 释放设备号 */ 53 } /* 其他代码同代码清单 6.16 */ 代码清单 6.18 第 7 行调用的 container_of() 的作用是通过结构体成员的指针找到对应结构体的指针, 这个技 巧在 Linux 内核编程中十分常用 在 container_of(inode->i_cdev,struct globalmem_dev,cdev) 语句中, 传给 container_of() 的第 1 个参数是结构体成员的指针, 第 2 个参数为整个结构体的类型, 第 3 个参数为传入的第 1 个参数即结构体成员的类型,container_of() 返回值为整个结构体的指针 下面是代码清单 6.18 针对 6.17 的 patch: 36c38,41 < filp->private_data = globalmem_devp; --- > struct globalmem_dev *dev; > > dev = container_of(inode->i_cdev,struct globalmem_dev,cdev); > filp->private_data = dev; 198c203 < result = register_chrdev_region(devno, 1, "globalmem"); --- > result = register_chrdev_region(devno, 2, "globalmem"); 201c206 < result = alloc_chrdev_region(&devno, 0, 1, "globalmem"); --- > result = alloc_chrdev_region(&devno, 0, 2, "globalmem"); 207,208c212,213 < /* 动态申请设备结构体的内存 */ < globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL); --- > /* 动态申请两个设备结构体的内存 */ > globalmem_devp = kmalloc(2*sizeof(struct globalmem_dev), GFP_KERNEL); 214c219 < memset(globalmem_devp, 0, sizeof(struct globalmem_dev)); --- > memset(globalmem_devp, 0, 2*sizeof(struct globalmem_dev)); 216c221,222 < globalmem_setup_cdev(globalmem_devp, 0); --- > globalmem_setup_cdev(&globalmem_devp[0], 0); > globalmem_setup_cdev(&globalmem_devp[1], 1); 226c232,233 < cdev_del(&globalmem_devp->cdev); /* 注销 cdev*/ --- > cdev_del(&(globalmem_devp[0].cdev)); > cdev_del(&(globalmem_devp[1].cdev)); /* 注销 cdev*/ 228c235 < unregister_chrdev_region(mkdev(globalmem_major, 0), 1); /* 释放设备号 */ --- > unregister_chrdev_region(mkdev(globalmem_major, 0), 2); /* 释放设备号 */ 19

20 1 globalmem 驱动在用户空间的验证 编译 globalmem 的驱动, 得到 globalmem.ko 文件 运行 insmod globalmem.ko 命令加载模块, 通过 lsmod 命令, 发现 globalmem 模块已被加载 再通过 cat /proc/devices 命令查看, 发现多出了主设备号为 254 的 globalmem 字符设备驱动, 如下所示 : [root@localhost driver_study]# cat /proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 /dev/vc/0 4 tty 5 /dev/tty 5 /dev/console 5 /dev/ptmx 7 vcs 10 misc 13 input 21 sg 29 fb 128 ptm 136 pts 171 ieee usb 189 usb_device 254 globalmem 接下来, 通过 mknod /dev/globalmem c 命令创建 /dev/globalmem 设备节点, 并通过 echo 'hello world' > /dev/globalmem 命令和 cat /dev/globalmem 命令分别验证设备的写和读, 结果证明 hello world 字符串被正确地写入 globalmem 字符设备 : [root@localhost driver_study]# echo 'hello world' > /dev/globalmem [root@localhost driver_study]# cat /dev/globalmem hello world 如果启用了 sysfs 文件系统, 将发现多出了 /sys/module/globalmem 目录, 该目录下的树型结构如下所示 : -- refcnt '-- sections --.bss --.data --.gnu.linkonce.this_module --.rodata --.rodata.str strtab --.symtab --.text '-- versions refcnt 记录了 globalmem 模块的引用计数,sections 下包含的多个文件则给出了 globalmem 所包含的 BSS 数据段和代码段等的地址及其他信息 对于代码清单 6.18 给出的支持两个 globalmem 设备的驱动, 在加载模块后需创建两个设备节点, /dev/globalmem0 对应主设备号 globalmem_major, 次设备号 0, /dev/globalmem1 对应主设备号 globalmem_major, 次设备号 1 分别读写/dev/globalmem0 和 /dev/globalmem1, 发现都读写到了正确的对应设备 20

21 1.7 总结 字符设备是 3 大类设备 ( 字符设备 块设备和网络设备 ) 中较简单的一类设备, 其驱动程序中完成的主要工作是初始化 添加和删除 cdev 结构体, 申请和释放设备号, 以及填充 file_operations 结构体中的操作函数, 实现 file_operations 结构体中的 read() write() 和 ioctl() 等函数是驱动设计的主体工作 联系方式 集团官网 : 嵌入式学院 : 移动互联网学院 : 企业学院 : 物联网学院 : 研发中心 :dev.hqyj.com 集团总部地址 : 北京市海淀区西三旗悦秀路北京明园大学校内华清远见教育集团 北京地址 : 北京市海淀区西三旗悦秀路北京明园大学校区, 电话 : /5 上海地址 : 上海市徐汇区漕溪路银海大厦 A 座 8 层, 电话 : 深圳地址 : 深圳市龙华新区人民北路美丽 AAA 大厦 15 层, 电话 : 成都地址 : 成都市武侯区科华北路 99 号科华大厦 6 层, 电话 : 南京地址 : 南京市白下区汉中路 185 号鸿运大厦 10 层, 电话 : 武汉地址 : 武汉市工程大学卓刀泉校区科技孵化器大楼 8 层, 电话 : 西安地址 : 西安市高新区高新一路 12 号创业大厦 D3 楼 5 层, 电话 :

static struct file_operations gpio_ctl_fops={ ioctl: gpio_ctl_ioctl, open : gpio_open, release: gpio_release, ; #defineled1_on() (GPBDAT &= ~0x1) #def

static struct file_operations gpio_ctl_fops={ ioctl: gpio_ctl_ioctl, open : gpio_open, release: gpio_release, ; #defineled1_on() (GPBDAT &= ~0x1) #def Kaise s 2410 Board setting [1]. Device Driver Device Driver Linux s Kernel ARM s kernel s3c2410_kernel2.4.18_r1.1_change.tar.bz2 /usr/src (1) #cd /usr/src (2) #tar xfj s3c2410_kernel2.4.18_r1.1_change.tar.bz2

More information

华恒家庭网关方案

华恒家庭网关方案 LINUX V1.5 1 2 1 2 LINUX WINDOWS PC VC LINUX WINDOWS LINUX 90% GUI LINUX C 3 REDHAT 9 LINUX PC TFTP/NFS http://www.hhcn.com/chinese/embedlinux-res.html minicom NFS mount C HHARM9-EDU 1 LINUX HHARM9-EDU

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,

More information

C/C++ - 文件IO

C/C++ - 文件IO C/C++ IO Table of contents 1. 2. 3. 4. 1 C ASCII ASCII ASCII 2 10000 00100111 00010000 31H, 30H, 30H, 30H, 30H 1, 0, 0, 0, 0 ASCII 3 4 5 UNIX ANSI C 5 FILE FILE 6 stdio.h typedef struct { int level ;

More information

<4D F736F F D20B5DA32D5C220416E64726F6964BFAAB7A2BBB7BEB3B4EEBDA82E646F6378>

<4D F736F F D20B5DA32D5C220416E64726F6964BFAAB7A2BBB7BEB3B4EEBDA82E646F6378> Android 应用程序开发与典型案例 作者 : 华清远见 第 2 章 Android 开发环境搭建 本章简介 本章主要介绍在 Windows 环境下,Android 开发环境的搭建步骤及注意事项, 包括 JDK 和 Java 开发环境的安装和配置 Eclipse 的安装 Android SDK 和 ADT 的安装和配置等 ; 同时介绍了 Android 开发的基本步骤 2.1 Android 开发环境的安装与配置

More information

<4D F736F F D20C7B6C8EBCABDCFB5CDB3BFAAB7A2CAB5D1E9CBC42E646F63>

<4D F736F F D20C7B6C8EBCABDCFB5CDB3BFAAB7A2CAB5D1E9CBC42E646F63> 嵌入式系统实验四 Linux 下设备驱动程序的开发 3.1 设备驱动程序的开发流程 进行嵌入式 Linux 系统的开发, 很大的工作量是为各种设备编写驱动程序 在 ARM 平台上开发嵌入式 Linux 的设备驱动程序与在其他平台上开发是一样的 总的来说, 实现一个嵌入式 Linux 设备驱动的大致流程如下 : (1) 查看原理图, 理解设备的工作原理 (2) 定义主设备号 (3) 在驱动程序中实现驱动的初始化

More information

第11章 可调内核参数

第11章 可调内核参数 11 11 Unix BSD 4.4 Linux sysctl Unix Linux /proc window /proc /proc/sys /proc/sys sysctl Unix root /proc/sys/vm root /proc/sys sysctl /proc/sys struct ctl_table 18274 struct ctl_tables /proc/sys struct

More information

<4D F736F F F696E74202D20B5DAB6FEBDB2A3BAC7B6C8EBCABD4C696E75782D416E64726F6964C7FDB6AFBFAAB7A2BDD2C3D8D6AED2BABEA7C6C1C7FDB6AFBFAAB7A22DB9F9C0CFCAA62E BBCE6C8DDC4A3CABD5D>

<4D F736F F F696E74202D20B5DAB6FEBDB2A3BAC7B6C8EBCABD4C696E75782D416E64726F6964C7FDB6AFBFAAB7A2BDD2C3D8D6AED2BABEA7C6C1C7FDB6AFBFAAB7A22DB9F9C0CFCAA62E BBCE6C8DDC4A3CABD5D> 在线大讲堂 手机驱动开发揭秘之液晶屏驱动开发 版权 华清远见嵌入式培训中心版权所有 ; 未经华清远见明确许可, 不能为任何目的以任何形式复制或传播此文档的任何部分 ; 本文档包含的信息如有更改, 恕不另行通知 ; 保留所有权利 2 主要内容 1. 液晶屏技术背景 2. 液晶屏接口分析 3. 液晶屏驱动框架分析 液晶屏与触摸屏关系 显示输出 控制输入 液晶屏与触摸屏关系 输入设备 软件 计算机硬件接口

More information

Microsoft Word - 实用案例.doc

Microsoft Word - 实用案例.doc 计 算 机 系 统 应 用 2009 年 第 12 期 嵌 入 式 Linux 下 温 湿 度 传 感 器 的 设 计 与 实 现 1 Design and Implementation of Temperature and Humidity Sensor Based on Embedded Linux 陈 博 刘 锦 高 ( 华 东 师 范 大 学 电 子 科 学 技 术 系 上 海 200241)

More information

新・明解C言語入門編『索引』

新・明解C言語入門編『索引』 !... 75!=... 48 "... 234 " "... 9, 84, 240 #define... 118, 213 #include... 148 %... 23 %... 23, 24 %%... 23 %d... 4 %f... 29 %ld... 177 %lf... 31 %lu... 177 %o... 196 %p... 262 %s... 242, 244 %u... 177

More information

Microsoft Word - 第4章 Linux内核模块

Microsoft Word - 第4章  Linux内核模块 LINUX 设备驱动开发详解 作者 : 华清远见 第 4 章 Linux 内核模块 Linux Linux Linux 4.1 4.2 Linux 4.3 4.8 Linux 4.1 4.2 4.3 4.8 4.9 Linux Makefile Linux 内核模块简介 Linux 内核的整体结构非常庞大, 其包含的组件也非常多 我们怎样把需要的部分都包含在内核中呢? 一种方法是把所有需要的功能都编译到

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

DVK530/531扩展板

DVK530/531扩展板 DVK720 扩展板 驱动移植手册 2014.04.03 V1.0 版权声明 本手册所有权由深圳市微雪电子有限公司独家持有 未经本公司的书 面许可, 不得以任何方式或形式进行修改 分发或复制本文档的任何 部分, 否则一切后果由违者自负 版本更新记录 版本日期说明 V1.0 2014.04.03 初始发布 深圳市微雪电子有限公司 www.waveshare.net I 目录 版权声明... I 版本更新记录...

More information

Agilent N5700 N5741A-49A, N5750A-52A, N5761A-69A, N5770A-72A W 1500 W 600 V 180 A 1 U Vac AC LAN,USB GPIB Agilent N5700 1U 750W 1500W 24

Agilent N5700 N5741A-49A, N5750A-52A, N5761A-69A, N5770A-72A W 1500 W 600 V 180 A 1 U Vac AC LAN,USB GPIB Agilent N5700 1U 750W 1500W 24 Agilent N700 N71A-9A, N70A-2A, N761A-69A, N770A-72A 2 70 W 100 W 600 V 180 A 1 U 8-26 Vac AC LAN,USB GPIB Agilent N700 1U 70W 100W 2 6V 600V 1.A 180A N700 1U 19 100W LED N700 OVP UVL UVL OVP N700 GPIB

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

ebook15-C

ebook15-C C 1 1.1 l s ( 1 ) - i i 4. 14 - d $ l s -ldi /etc/. /etc/.. - i i 3077 drwxr-sr-x 7 bin 2048 Aug 5 20:12 /etc/./ 2 drwxr-xr-x 13 root 512 Aug 5 20:11 /etc/../ $ls -ldi /. /..... i 2 2 drwxr-xr-x 13 root

More information

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++; Memory & Pointer trio@seu.edu.cn 2.1 2.1.1 1 int *p int a 0x00C7 0x00C7 0x00C7 2.1.2 2 int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++; 2.1.3 1. 2. 3. 3 int A,

More information

Microsoft PowerPoint - Chapter7-DriverDevices.ppt

Microsoft PowerPoint - Chapter7-DriverDevices.ppt Chapter 7 Device Drivers and Software Interface Design Professor Ching-Lung Su E-mail: kevinsu@yuntech.edu.tw Http://www.eecs.yuntech.edu.tw NYUST/EL P-2/80 Outline 7.1 Introduction to Device Driver 7.2

More information

第 14 行调用 of_demo_controller_register 注册 demo controller 驱动,xlate 函数设置的都是 of_demo_simple_xlate, 这个函数完成对 user 传来的参数的处理 1. int of_demo_controller_registe

第 14 行调用 of_demo_controller_register 注册 demo controller 驱动,xlate 函数设置的都是 of_demo_simple_xlate, 这个函数完成对 user 传来的参数的处理 1. int of_demo_controller_registe 作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Linux 4.10.17 概述 上一篇大概介绍了一下 demo controller 的结构, 下面结合驱动分析 正文 一 demo controller 驱动 这里主要分析 probe 函数 demo_controller_probe: 1. static int demo_controller_probe(struct

More information

新版 明解C++入門編

新版 明解C++入門編 511!... 43, 85!=... 42 "... 118 " "... 337 " "... 8, 290 #... 71 #... 413 #define... 128, 236, 413 #endif... 412 #ifndef... 412 #if... 412 #include... 6, 337 #undef... 413 %... 23, 27 %=... 97 &... 243,

More information

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc 2 5 8 11 0 13 1. 13 2. 15 3. 18 1 23 1. 23 2. 26 3. 28 2 36 1. 36 2. 39 3. 42 4. 44 5. 49 6. 51 3 57 1. 57 2. 60 3. 64 4. 66 5. 70 6. 75 7. 83 8. 85 9. 88 10. 98 11. 103 12. 108 13. 112 4 115 1. 115 2.

More information

[公司名称]

[公司名称] 嵌入式培训专家 Linux 设备驱动开发 www.farsight.com.cn 今天的内容 Linux 设备驱动的现状从 non os 驱动到 Linux 驱动内核设施 自旋锁 信号量 互斥量 完成量 异步通知 信号 阻塞与非阻塞 内存与 I/O 操作, DMA 中断, top half/bottom half 字符设备驱动复杂设备驱动的框架 LCD 设备 FRAMEBUFFER FLASH 设备

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 177 [P179] (1) - [P181] [P182] (2) - for [P183] (3) - switch [P184] [P187] [P189] [P194] 178 [ ]; : : int var; : int var[3]; var 2293620 var[0] var[1] 2293620

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

Microsoft Word - 第6章 Android驱动编程.docx

Microsoft Word - 第6章 Android驱动编程.docx Android 系统移植和驱动开发 作者 : 华清远见 第 6 章 Android 驱动编程 本章目标 本章将进入到 Android 的内核空间, 初步介绍嵌入式 Android 设备驱动的开发 驱动的开发流程相对于应用程序的开发是全新的, 与读者以前的编程习惯完全不同, 希望读者能尽快熟悉环境 本章主要内容 : 设备驱动概述 字符设备驱动编程 GPIO 驱动程序实例 4 4 扫描键盘驱动 6.1

More information

JLX

JLX PRODUCT:LCD MODULE. Model No.: JLX177-006 Product Type: 1.77 inch QVGA TFT Modoule. 产品规格书 晶联讯研发研发部 : Written By Checked By Approved By 客户名称 : 结构电子核准 地址 : 深圳市宝安区西乡宝安大道东华工业区 A3 栋 6 楼电话 :0755-29784961 Http://www.jlxlcd.cn

More information

嵌入式Linux知识培训

嵌入式Linux知识培训 嵌入式 Linux 知识培训 主要包括以下四部分内容 : 一 嵌入式 Linux 开发的基本知识 二 Linux 下使用 C 语言进行系统开发 三 面向嵌入式 Linux 的 GUI 系统的体系结构及二次开发 四 基于 Linux OS Smart Phone 的体系结构及开发内容 李玉东 第一部分 基础知识 嵌入式 Linux 软件系统的构成 1.BootLoader 2. Kernel 3.FileSystem

More information

ebook15-12

ebook15-12 1 2I / O 12.1 I / O V I / O s e l e c tp o l l r e a d vw r i t e v I / Om m a p 14 15 12.2 I / O 1 0. 5 F I F O F I F O i o c t l 14 I / O I / o p e n, r e a dw r i t e I / O (1) o p e n O _ N O N B L

More information

《C语言程序设计》教材习题参考答案

《C语言程序设计》教材习题参考答案 教材名称 : C 语言程序设计 ( 第 1 版 ) 黄保和 江弋编著清华大学出版社 ISBN:978-7-302-13599-9, 红色封面 答案制作时间 :2011 年 2 月 -5 月 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p=&a 2. 设已定义 int x,*p=&x;, 则下列表达式中错误的是 :B)&*x 3. 若已定义 int a=1,*b=&a;,

More information

<4D6963726F736F667420576F7264202D20B5DA38D5C220204C696E7578C9E8B1B8C7FDB6AFD6D0B5C4D7E8C8FBD3EBB7C7D7E8C8FB494F>

<4D6963726F736F667420576F7264202D20B5DA38D5C220204C696E7578C9E8B1B8C7FDB6AFD6D0B5C4D7E8C8FBD3EBB7C7D7E8C8FB494F> LINUX 设 备 驱 动 开 发 详 解 作 者 : 华 清 远 见 第 8 章 Linux 设 备 驱 动 中 的 阻 塞 与 非 阻 塞 I/O I/O 8.1 I/O I/O I/O globalfifo I/O 8.2 poll poll 8.3 globalfifo poll 阻 塞 与 非 阻 塞 I/O 阻 塞 操 作 是 指 在 执 行 设 备 操 作 时 若 不 能 获 得 资

More information

C 1

C 1 C homepage: xpzhangme 2018 5 30 C 1 C min(x, y) double C // min c # include # include double min ( double x, double y); int main ( int argc, char * argv []) { double x, y; if( argc!=

More information

<4D F736F F D20B5DA33D5C22020B6E0BACBCDA8D0C5>

<4D F736F F D20B5DA33D5C22020B6E0BACBCDA8D0C5> ANDROID 多媒体编程从初学到精通 作者 : 华清远见 第 3 章 多核通信 -- Qucalcomm MSM 7K 4 Qucalcomm MSM 7K ARM 9 marm modem ARM mdsp Modem DSP ARM 11 aarm application ARM Linux adsp Application DSP / 2010 CPU Cortex-A8 Nvidia Cortex-A9

More information

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha CYPOK CYPOK 1 UltraEdit Project-->Install Language Tool: Language Suite----->hi-tech picc Tool Name ---->PICC Compiler Executable ---->c:hi-picinpicc.exe ( Command-line Project-->New Project-->File Name--->myc

More information

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023)

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023) ( CIP) /. :, 2005. 2 ( ) ISBN 7-5624-3339-9.......... TP311. 1 CIP ( 2005) 011794 : : : : * : : 174 ( A ) :400030 : ( 023) 65102378 65105781 : ( 023) 65103686 65105565 : http: / /www. cqup. com. cn : fxk@cqup.

More information

NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p

NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p NOWOER.OM /++ 程师能 评估. 单项选择题 1. 下 描述正确的是 int *p1 = new int[10]; int *p2 = new int[10](); p1 和 p2 申请的空间 的值都是随机值 p1 和 p2 申请的空间 的值都已经初始化 p1 申请的空间 的值是随机值,p2 申请的空间 的值已经初始化 p1 申请的空间 的值已经初始化,p2 申请的空间 的值是随机值 2.

More information

C/C++语言 - C/C++数据

C/C++语言 - C/C++数据 C/C++ C/C++ Table of contents 1. 2. 3. 4. char 5. 1 C = 5 (F 32). 9 F C 2 1 // fal2cel. c: Convert Fah temperature to Cel temperature 2 # include < stdio.h> 3 int main ( void ) 4 { 5 float fah, cel ;

More information

1.01

1.01 2013 操作系统课程设计 内容简介 设计目的 设计内容 实施方法及要求 时间安排 辅导 2 设计目的 掌握 Linux 操作系统的使用方法 ; 了解 Linux 系统内核代码结构 ; 掌握实例操作系统的实现方法 3 内容简介 设计目的 设计内容 实施方法及要求 时间安排 辅导 4 设计内容 (1) 要求 : 熟悉和理解 Linux 编程环境 内容 编写一个 C 程序, 使用 Linux 下的图形库,

More information

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit 6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C51 6.1 C51 6.1.1 C51 C51 ANSI C MCS-51 C51 ANSI C C51 6.1 6.1 C51 bit Byte bit sbit 1 0 1 unsigned char 8 1 0 255 Signed char 8 11 128

More information

FY.DOC

FY.DOC 高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主

More information

2 Linux 设备驱动开发详解 : 基于最新的 Linux 4.0 内核 也就是说, 应用软件工程师需要看到一个没有硬件的纯粹的软件世界, 硬件必须透明地呈现给他 谁来实现硬件对应用软件工程师的隐形? 这个光荣而艰巨的任务就落在了驱动工程师的头上 对设备驱动最通俗的解释就是 驱使硬件设备行动 驱动

2 Linux 设备驱动开发详解 : 基于最新的 Linux 4.0 内核 也就是说, 应用软件工程师需要看到一个没有硬件的纯粹的软件世界, 硬件必须透明地呈现给他 谁来实现硬件对应用软件工程师的隐形? 这个光荣而艰巨的任务就落在了驱动工程师的头上 对设备驱动最通俗的解释就是 驱使硬件设备行动 驱动 第 1 章 Linux 设备驱动概述及开发环境构建 本章导读本章将介绍 Linux 设备驱动开发的基本概念, 并对本书所基于的平台和开发环境进行讲解 1.1 节阐明设备驱动的概念和作用 1.2 节和 1.3 节分别讲解在无操作系统情况下和有操作系统情况下设备驱动的设计, 通过对设计差异的分析, 讲解设备驱动与硬件和操作系统的关系 1.4 节对 Linux 操作系统的设备驱动进行了概要性的介绍, 给出设备驱动与整个软硬件系统的关系,

More information

C语言的应用.PDF

C语言的应用.PDF AVR C 9 1 AVR C IAR C, *.HEX, C,,! C, > 9.1 AVR C MCU,, AVR?! IAR AVR / IAR 32 ALU 1KBytes - 8MBytes (SPM ) 16 MBytes C C *var1, *var2; *var1++ = *--var2; AVR C 9 2 LD R16,-X ST Z+,R16 Auto (local

More information

Microsoft PowerPoint - string_kruse [兼容模式]

Microsoft PowerPoint - string_kruse [兼容模式] Strings Strings in C not encapsulated Every C-string has type char *. Hence, a C-string references an address in memory, the first of a contiguous set of bytes that store the characters making up the string.

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

C

C C 14 2017 5 31 1. 2. 3. 4. 5. 2/101 C 1. ( ) 4/101 C C ASCII ASCII ASCII 5/101 C 10000 00100111 00010000 ASCII 10000 31H 30H 30H 30H 30H 1 0 0 0 0 0 ASCII 6/101 C 7/101 C ( ) ( ) 8/101 C UNIX ANSI C 9/101

More information

全国计算机技术与软件专业技术资格(水平)考试

全国计算机技术与软件专业技术资格(水平)考试 全 国 计 算 机 技 术 与 软 件 专 业 技 术 资 格 ( 水 平 ) 考 试 2008 年 上 半 年 程 序 员 下 午 试 卷 ( 考 试 时 间 14:00~16:30 共 150 分 钟 ) 试 题 一 ( 共 15 分 ) 阅 读 以 下 说 明 和 流 程 图, 填 补 流 程 图 中 的 空 缺 (1)~(9), 将 解 答 填 入 答 题 纸 的 对 应 栏 内 [ 说 明

More information

《C语言程序设计》第2版教材习题参考答案

《C语言程序设计》第2版教材习题参考答案 教材 C 语言程序设计 ( 第 2 版 ) 清华大学出版社, 黄保和, 江弋编著 2011 年 10 月第二版 ISBN:978-7-302-26972-4 售价 :35 元 答案版本 本习题答案为 2012 年 2 月修订版本 一 选择题 1. 设已定义 int a, * p, 下列赋值表达式中正确的是 :C)p = &a A. *p = *a B. p = *a C.p = &a D. *p =

More information

nooog

nooog C : : : , C C,,, C, C,, C ( ), ( ) C,,, ;,, ; C,,, ;, ;, ;, ;,,,, ;,,, ; : 1 9, 2 3, 4, 5, 6 10 11, 7 8, 12 13,,,,, 2008 1 1 (1 ) 1.1 (1 ) 1.1.1 ( ) 1.1.2 ( ) 1.1.3 ( ) 1.1.4 ( ) 1.1.5 ( ) 1.2 ( ) 1.2.1

More information

<4D F736F F F696E74202D20C7B6C8EBCABDC7FDB6AFBFAAB7A22DD2D7CBC9BBAA2E BBCE6C8DDC4A3CABD5D>

<4D F736F F F696E74202D20C7B6C8EBCABDC7FDB6AFBFAAB7A22DD2D7CBC9BBAA2E BBCE6C8DDC4A3CABD5D> 嵌入式开发之 linux 驱动开发入门 易老师, 深圳中心 华清远见全国免费咨询电话 :400-706-1880 深圳中心咨询电话 : 0755-25590506 Topics... 1.LINUX 驱动干什么用的? 2. 现在企业需要什么底层驱动人才? 3. 如何成为嵌入式底层人才? 4.LINUX 驱动和单片机开发有何异同 5.LINUX 设备驱动的架构分析 6.LCD 的硬件原理分析 7.LCD

More information

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf (%d, & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf (%d %d 2013 18 ( ) 1. C pa.c, pb.c, 2. C++ pa.cpp, pb.cpp, Compilation Error cin scanf Time Limit Exceeded 1: A 5 B 5 C 5 D 5 E 5 F 5 1 2013 C 1 # include 2 int main ( void ) 3 { 4 int cases, a, b,

More information

文件

文件 CH10 文件 1 文件的概念 一 文件分类 二 文件的组织结构 : ASCII 码文件 ( 文本文件 ) 二进制文件 文件是二进制代码的, 则文件就是字节流 文件是 ASCII 码的, 则文件就是字符流, 也是字节流 1 如 : 对于整型变量 x, 其值为 32767 若以文本方式存放, 则共有 5 个字符, 内容为 : 00110011 00110010 00110111 00110110 00110111

More information

嵌入式Linux块设备驱动开发解析

嵌入式Linux块设备驱动开发解析 The success's road 嵌 入 式 LINUX 网 络 驱 动 开 发 Copyright 2007-2008 Farsight. All rights reserved. 要 点 Linux 网 络 设 备 驱 动 程 序 概 述 计 算 机 网 络 概 述 skbuf 数 据 结 构 介 绍 Linux 网 络 设 备 驱 动 程 序 API 介 绍 Linux 网 络 设 备 驱

More information

System Developement——第二.ppt

System Developement——第二.ppt 嵌入式培训专家 Linux 设备驱动开发 主讲 : 宋宝华 www.farsight.com.cn 今天的内容 Linux 设备驱动的现状从 non-os 驱动到 Linux 驱动内核设施 自旋锁 信号量 互斥量 完成量 异步通知 信号 阻塞与非阻塞 内存与 I/O 操作,DMA 中断,top half/bottom half 字符设备驱动复杂设备驱动的框架 LCD 设备 FRAMEBUFFER FLASH

More information

谨将我们的工作献给 即将毕业离校的兄弟们 林晓鑫 刘德超 黄巍 周蓝珺 胡禹轩 王新喜 何春晓 崔剑 李浩 以及 潘海东即将出世的小 Baby! II

谨将我们的工作献给 即将毕业离校的兄弟们 林晓鑫 刘德超 黄巍 周蓝珺 胡禹轩 王新喜 何春晓 崔剑 李浩 以及 潘海东即将出世的小 Baby! II 谨将我们的工作献给 即将毕业离校的兄弟们 林晓鑫 刘德超 黄巍 周蓝珺 胡禹轩 王新喜 何春晓 崔剑 李浩 以及 潘海东即将出世的小 Baby! II 0 译者序 Linux System Prorgramming ( LSP) 的 文 工作 实 工业 IBM 理 的 工作的同 的 同 们 林晓鑫 王 崔 春 何春晓 李 的 SMS@lilacbbs.com 文献 的 王 刘文 王 刘德超 王新喜

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3 浙江大学 C 程序设计及实验 试题卷 2002-2003 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:30-10:30 注意 : 答题内容必须写在答题卷上, 写在本试题卷上无效 一. 单项选择题 ( 每题 1 分, 共 10 分 ) 1. 下列运算符中, 优先级最低的是 A.

More information

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式] 指针 Pointers 变量指针与指针变量 Pointer of a variable 变量与内存 (Variables and Memory) 当你声明一个变量时, 计算机将给该变量一个内存, 可以存储变量的值 当你使用变量时, 计算机将做两步操作 : - 根据变量名查找其对应的地址 ; - 通过地址对该地址的变量内容进行读 (retrieve) 或写 (set) 变量的地址称为变量的指针! C++

More information

SEP4020 Linux2

SEP4020 Linux2 SEP4020 Linux2.6.16 SDK Develop Manual Version 3.4 南京博芯电子技术有限公司 2009 11 版权声明 本手册版权归属南京博芯电子技术有限公司所有, 并保留一切权力 没有南京博芯电子技术有限公司的许可 ( 书面形式 ), 任何单位及个人不得擅自摘录本手册部分或全部, 违者我们将追究其法律责任 TEL:025-83196327 FAX:025-83196326

More information

A Preliminary Implementation of Linux Kernel Virus and Process Hiding

A Preliminary Implementation of Linux Kernel Virus and Process Hiding 邵 俊 儒 翁 健 吉 妍 年 月 日 学 号 学 号 学 号 摘 要 结 合 课 堂 知 识 我 们 设 计 了 一 个 内 核 病 毒 该 病 毒 同 时 具 有 木 马 的 自 动 性 的 隐 蔽 性 和 蠕 虫 的 感 染 能 力 该 病 毒 获 得 权 限 后 会 自 动 将 自 身 加 入 内 核 模 块 中 劫 持 的 系 统 调 用 并 通 过 简 单 的 方 法 实 现 自 身 的

More information

第11章、嵌入式Linux设备驱动开发

第11章、嵌入式Linux设备驱动开发 黑色经典 系列之 嵌入式 Linux 应用程序开发详解 第 11 章嵌入式 Linux 设备驱动开发 本章目标 本书从第 6 章到第 10 章详细讲解了嵌入式 Linux 应用程序的开 发, 这些都是处于用户空间的内容 本章将进入到 Linux 的内核空间, 初步介绍嵌入式 Linux 设备驱动的开发 驱动的开发流程相对于应用 程序的开发是全新的, 与读者以前的编程习惯完全不同, 希望读者能 尽快地熟悉现在环境

More information

C/C++程序设计 - 字符串与格式化输入/输出

C/C++程序设计 - 字符串与格式化输入/输出 C/C++ / Table of contents 1. 2. 3. 4. 1 i # include # include // density of human body : 1. 04 e3 kg / m ^3 # define DENSITY 1. 04 e3 int main ( void ) { float weight, volume ; int

More information

untitled

untitled 1 DBF (READDBF.C)... 1 2 (filetest.c)...2 3 (mousetes.c)...3 4 (painttes.c)...5 5 (dirtest.c)...9 6 (list.c)...9 1 dbf (readdbf.c) /* dbf */ #include int rf,k,reclen,addr,*p1; long brec,erec,i,j,recnum,*p2;

More information

S3C6410 ARM11开发板Linux BSP构建

S3C6410 ARM11开发板Linux BSP构建 嵌入式培训专家 S3C6410 ARM11 开发板 Linux BSP 构建 主讲 : 宋宝华 www.farsight.com.cn 今天的内容 vbsp 的组成部分 vplat/mach 各组件的实现 内核节拍 中断管理 时钟 GPIO DMA IO 内存映射 v 设备与资源 platform device resource 和 plarform data uart/spi/i2c 等设备板级

More information

INTRODUCTION TO COM.DOC

INTRODUCTION TO COM.DOC How About COM & ActiveX Control With Visual C++ 6.0 Author: Curtis CHOU mahler@ms16.hinet.net This document can be freely release and distribute without modify. ACTIVEX CONTROLS... 3 ACTIVEX... 3 MFC ACTIVEX

More information

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File 51 C 51 51 C C C C C C * 2003-3-30 pnzwzw@163.com C C C C KEIL uvision2 MCS51 PLM C VC++ 51 KEIL51 KEIL51 KEIL51 KEIL 2K DEMO C KEIL KEIL51 P 1 1 1 1-1 - 1 Project New Project 1 2 Windows 1 3 N C test

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

C/C++语言 - 分支结构

C/C++语言 - 分支结构 C/C++ Table of contents 1. if 2. if else 3. 4. 5. 6. continue break 7. switch 1 if if i // colddays.c: # include int main ( void ) { const int FREEZING = 0; float temperature ; int cold_ days

More information

Linux内核的移植技术剖析

Linux内核的移植技术剖析 嵌入式培训专家 Linux 内核的移植技术剖析 主讲 : 宋宝华 www.farsight.com.cn 今天的内容 vbsp 的组成部分 vplat/mach 各组件的实现 内核节拍 中断管理 时钟 GPIO DMA IO 内存映射 v 设备与资源 platform device resource 和 plarform data uart/spi/i2c 等设备板级 resource vbsp 作用

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

Microsoft Word - PHP7Ch01.docx

Microsoft Word - PHP7Ch01.docx PHP 01 1-6 PHP PHP HTML HTML PHP CSSJavaScript PHP PHP 1-6-1 PHP HTML PHP HTML 1. Notepad++ \ch01\hello.php 01: 02: 03: 04: 05: PHP 06:

More information

Microsoft Word - 第1章 绪论.docx

Microsoft Word - 第1章 绪论.docx Windows CE 嵌入式开发标准教程 作者 : 华清远见 第 1 章绪论 本章目标 本章概述了嵌入式操作系统的概念 系统特性和 Windows CE 操作系统的发展 历史 开发特性以及开发流程 通过本章的学习, 读者将会掌握以下内容 了解嵌入式操作系统的基本特点了解 Windows CE 操作系统的发展历史掌握 Windows CE 操作系统的主要特性掌握 Windows CE 的开发特点掌握

More information

Microsoft Word - 11.doc

Microsoft Word - 11.doc 除 錯 技 巧 您 將 於 本 章 學 到 以 下 各 項 : 如 何 在 Visual C++ 2010 的 除 錯 工 具 控 制 下 執 行 程 式? 如 何 逐 步 地 執 行 程 式 的 敘 述? 如 何 監 看 或 改 變 程 式 中 的 變 數 值? 如 何 監 看 程 式 中 計 算 式 的 值? 何 謂 Call Stack? 何 謂 診 斷 器 (assertion)? 如 何

More information

SEP4020 Linux2

SEP4020 Linux2 SEP4020 Linux2.6.16 SDK Develop Manual Version 3.4.4 南京博芯电子技术有限公司 2009 年 12 月 版权声明 本手册版权归属南京博芯电子技术有限公司所有, 并保留一切权力 没有南京博芯电子技术有限公司的许可 ( 书面形式 ), 任何单位及个人不得擅自摘录本手册部分或全部, 违者我们将追究其法律责任 TEL:025-83196327 FAX:025-83196326

More information

untitled

untitled 3 C++ 3.1 3.2 3.3 3.4 new delete 3.5 this 3.6 3.7 3.1 3.1 class struct union struct union C class C++ C++ 3.1 3.1 #include struct STRING { typedef char *CHARPTR; // CHARPTR s; // int strlen(

More information

_汪_文前新ok[3.1].doc

_汪_文前新ok[3.1].doc 普 通 高 校 本 科 计 算 机 专 业 特 色 教 材 精 选 四 川 大 学 计 算 机 学 院 国 家 示 范 性 软 件 学 院 精 品 课 程 基 金 青 年 基 金 资 助 项 目 C 语 言 程 序 设 计 (C99 版 ) 陈 良 银 游 洪 跃 李 旭 伟 主 编 李 志 蜀 唐 宁 九 李 涛 主 审 清 华 大 学 出 版 社 北 京 i 内 容 简 介 本 教 材 面 向

More information

概述

概述 OPC Version 1.6 build 0910 KOSRDK Knight OPC Server Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOS_Init...5 2.2.2 KOS_InitB...5 2.2.3

More information

C/C++ 语言 - 循环

C/C++ 语言 - 循环 C/C++ Table of contents 7. 1. 2. while 3. 4. 5. for 6. 8. (do while) 9. 10. (nested loop) 11. 12. 13. 1 // summing.c: # include int main ( void ) { long num ; long sum = 0L; int status ; printf

More information

科学计算的语言-FORTRAN95

科学计算的语言-FORTRAN95 科 学 计 算 的 语 言 -FORTRAN95 目 录 第 一 篇 闲 话 第 1 章 目 的 是 计 算 第 2 章 FORTRAN95 如 何 描 述 计 算 第 3 章 FORTRAN 的 编 译 系 统 第 二 篇 计 算 的 叙 述 第 4 章 FORTRAN95 语 言 的 形 貌 第 5 章 准 备 数 据 第 6 章 构 造 数 据 第 7 章 声 明 数 据 第 8 章 构 造

More information

ebook 86-15

ebook 86-15 15 G t k + d e l e t e _ e v e n t G n o m e G n o m e 15.1 GnomeDialog G t k + G n o m e D i a l o g 15.1.1 G n o m e D i a l o g g n o m e _ d i a l o g _ n e w ( ) G N O M E _ D I A L O G ( d i a l

More information

51 C 51 isp 10 C PCB C C C C KEIL

51 C 51 isp 10   C   PCB C C C C KEIL http://wwwispdowncom 51 C " + + " 51 AT89S51 In-System-Programming ISP 10 io 244 CPLD ATMEL PIC CPLD/FPGA ARM9 ISP http://wwwispdowncom/showoneproductasp?productid=15 51 C C C C C ispdown http://wwwispdowncom

More information

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式] Arrays and Strings 存储同类型的多个元素 Store multi elements of the same type 数组 (array) 存储固定数目的同类型元素 如整型数组存储的是一组整数, 字符数组存储的是一组字符 数组的大小称为数组的尺度 (dimension). 定义格式 : type arrayname[dimension]; 如声明 4 个元素的整型数组 :intarr[4];

More information

C C

C C C C 2017 3 8 1. 2. 3. 4. char 5. 2/101 C 1. 3/101 C C = 5 (F 32). 9 F C 4/101 C 1 // fal2cel.c: Convert Fah temperature to Cel temperature 2 #include 3 int main(void) 4 { 5 float fah, cel; 6 printf("please

More information

目录 1. RK 支持的编解码类型 头文件与库文件 结构体介绍 编解码枚举定义 编解码结构体定义 解码调用流程 解码创建过程 解码过程 解码销毁过程

目录 1. RK 支持的编解码类型 头文件与库文件 结构体介绍 编解码枚举定义 编解码结构体定义 解码调用流程 解码创建过程 解码过程 解码销毁过程 vpu_api.h 接口说明文档 1 目录 1. RK 支持的编解码类型... 3 2. 头文件与库文件... 3 3. 结构体介绍... 3 3.1 编解码枚举定义... 3 3.2 编解码结构体定义... 5 4. 解码调用流程... 8 4.1 解码创建过程... 8 4.2 解码过程... 9 4.3 解码销毁过程... 9 5. 编码调用流程...10 5.1 编码创建过程...10 5.2

More information

PCMCIA Compact Flash GPRS GPS PCMCIA Personal Computer Memory Card International Association CF Compact Flash PCMCIA CF PCMCIA/CF

PCMCIA Compact Flash GPRS GPS PCMCIA Personal Computer Memory Card International Association CF Compact Flash PCMCIA CF PCMCIA/CF 09 PCMCIA Compact Flash GPRS GPS PCMCIA Personal Computer Memory Card International Association CF Compact Flash PCMCIA CF PCMCIA/CF PCMCIA WiFi Linux PCMCIA PCMCIA/CF 9-1 PCMCIA/CF PCMCIA 16 CF PCMCIA

More information

How to Debug Tuxedo Server printf( Input data is: %s, inputstr); fprintf(stdout, Input data is %s, inputstr); fprintf(stderr, Input data is %s, inputstr); printf( Return data is: %s, outputstr); tpreturn(tpsuccess,

More information

Ps22Pdf

Ps22Pdf C ( CIP) C /. :, 2001. 7 21 ISBN 7-5624 -2355-5. C........ C. TP312 CIP ( 2001 ) 034496 C * * : 7871092 1 /16 : 14. 25 : 356 20017 1 20017 1 : 1 6 000 ISBN 7-5624-2355-5 / TP311 : 21. 00 C, C,,,, C,, (

More information

没有幻灯片标题

没有幻灯片标题 指针作为函数参数 : 原因 : 1 需要修改一个或多个值,( 用 return 语句不能解决问题 ) 2 执行效率的角度 使用方法 : 在函数原型以及函数首部中需要声明能够接受指针值的形参, 具体的写法为 : 数据类型 * 形参名 如果有多个指针型形参, 则用逗号分隔, 例如 : void swap(int *p1, int *p2) 它说明了形参 p1 p2 是指向整型变量的指针 在函数调用时,

More information

Microsoft Word - 扉页

Microsoft Word - 扉页 第 3 章 文件系统简介 在 UNIX 族的操作系统中, 文件系统占有十分重要的地位, 文件的概念涵盖了 UNIX 设备和操作对象的全部内容, 对设备的操作方式几乎可以与对普通文件的操作等价 本章对文件系统进行简单的介绍, 主要包括如下内容 : Linux 下文件的内涵 ; Linux 下的文件系统布局和文件系统的树形结构 ; Linux 下的普通文件和设备文件 ; Linux 下虚拟文件系统的含义

More information

untitled

untitled MODBUS 1 MODBUS...1 1...4 1.1...4 1.2...4 1.3...4 1.4... 2...5 2.1...5 2.2...5 3...6 3.1 OPENSERIAL...6 3.2 CLOSESERIAL...8 3.3 RDMULTIBIT...8 3.4 RDMULTIWORD...9 3.5 WRTONEBIT...11 3.6 WRTONEWORD...12

More information

W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent UNIX CPU IO

W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent UNIX CPU IO Linux muduo C++ (giantchen@gmail.com) 2012-09-30 C++ TCP C++ x86-64 Linux TCP one loop per thread Linux native muduo C++ IT 5 C++ muduo 2 C++ C++ Primer 4 W. Richard Stevens UNIX Sockets API echo Sockets

More information

Go构建日请求千亿微服务最佳实践的副本

Go构建日请求千亿微服务最佳实践的副本 Go 构建 请求千亿级微服务实践 项超 100+ 700 万 3000 亿 Goroutine & Channel Goroutine Channel Goroutine func gen() chan int { out := make(chan int) go func(){ for i:=0; i

More information

ebook15-4

ebook15-4 4 4.1 I / O I / s t a t s t a t ( ) U N I X 4.2 stat fstat lstat s t a t #include #include int stat(const char p a * t h n a m e, struct stat b * u f) ; int fstat(int f i l e

More information

ebook35-14

ebook35-14 14 V F S L i n u x 14.1 S u p e r I O I D E I D E C S R, C S R L i n u x L i n u x I D E / d e v / h a d m k n o d I D E I D E / d e v / h d a 2 L i n u x Linux /dev/cua0 / d e v / c u a 1 512 1024 BSD

More information

/3/15 1, linux. linux,,. : 1.NAT ; 2. (load balance, virtual server);; 3. ; 4. ; 5. 6.VPN; 7. ; 8. ; 9.. (,

/3/15 1, linux. linux,,. : 1.NAT ; 2. (load balance, virtual server);; 3. ; 4. ; 5. 6.VPN; 7. ; 8. ; 9.. (, Yawl(yawl@docshownet) wwwdocshownet 2000/3/15 1, linux linux,, 1NAT ; 2 (load balance,virtual server);; 3 ; 4 ; 5 6VPN; 7 ; 8 ; 9 (,, )IP, (VPN,, ) IP, (call_in_firewall(),call_fw_firewall(),call_out_firewall(),

More information

华清远见就业优势倍增项目手册

华清远见就业优势倍增项目手册 Linux 内核编程与调试 宋宝华 版权 } 华清远见嵌入式培训中心版权所有 ; } 未经华清远见明确许可, 不能为任何目的以任何形式复制 或传播此文档的任何部分 ; } 本文档包含的信息如有更改, 恕不另行通知 ; } 保留所有权利 2 www.hqyj.com 原子操作 void atomic_set(atomic_t *v, int i); void atomic_add(int i, atomic_t

More information

Microsoft PowerPoint - BECKHOFF技术_ADS通讯 [Compatibility Mode]

Microsoft PowerPoint - BECKHOFF技术_ADS通讯 [Compatibility Mode] 的架构 ADS 的通讯机制 ADS-Client Request -> Confirmation Indication

More information

学习MSP430单片机推荐参考书

学习MSP430单片机推荐参考书 MSP430 16 MSP430 C MSP430 C MSP430 FLASH 16 1 CPU 16 ALU 16 PC SP SR R4~R15 2 3 00-FFH 100-1FFH 4 5 1 2 51 24 27 6 1 2 3 4 5 6 4 12 SR SP SR CPU SR CPU C Z N GIE CPUOff CPU OscOff SCG0 SCG1 CPU EXIT SP

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information