linux 驱动入门3
不吃苦中苦,难为人上人。努力,给老婆孩子提供个良好的生活居住环境。
http://www.cnblogs.com/nan-jing/articles/5806399.html
上文提到。可以自动创建了设备节点。这次我们研究下。如何创建/proc文件系统下的节点呢? 有如何实现/proc节点的读写呢?
老规矩,为了方便大家复制粘贴。我直接贴全部源码,复制下来,可以直接编译运行的。
#include<linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
//#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/proc_fs.h>
MODULE_AUTHOR("qcom.shanghai@gmail.com");
MODULE_LICENSE("Dual BSD/GPL");
#define GLOBALMEM_SIZE 0X1000
#define MEM_CLEAR 0x1
#define CJ_PROC_ENTRY "cjzang"
#define CJ_PROC_NODE "cj_entry"
static int globalmem_major = 0;
struct globalmem_dev{
struct cdev cdev;
unsigned char mem[GLOBALMEM_SIZE];
};
struct globalmem_dev *globalmem_devp;
struct class *globalmem_class;
struct proc_dir_entry *proc_cj_entry;
static int globalmem_open(struct inode *inode, struct file *filp){
struct globalmem_dev *dev;
dev = container_of(inode->i_cdev, struct globalmem_dev, cdev);
filp->private_data = dev; //臧春杰 marvell
printk(KERN_ALERT "globalmem_open!");
return 0;
}
static int globalmem_release(struct inode *inode, struct file *filp){
printk(KERN_ALERT "globalmem_release!");
return 0;
}
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data;
//臧春杰 honeywell
if (p >= GLOBALMEM_SIZE){
return 0;
}
if (count > GLOBALMEM_SIZE - p){
count = GLOBALMEM_SIZE - p;
}
if (copy_to_user(buf, (void *)(dev->mem + p), count)){
ret = - EFAULT;
}else {
*ppos += count;
ret = count;
printk(KERN_ALERT "read %u bytes from %lu \n", count, p);
}
return ret;
}
static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos){
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data;
if (p >= GLOBALMEM_SIZE){
return 0;
}
if (count > GLOBALMEM_SIZE - p){
count = GLOBALMEM_SIZE - p;
}
if (copy_from_user(dev->mem + p, buf, count)){
ret = - EFAULT;
}else {
*ppos += count;
ret = count;
printk(KERN_ALERT "write %u bytes from %lu \n", count, p);
}
return ret;
}
static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig){
loff_t ret = 0;
switch(orig){
case 0:
if (offset < 0){
ret = - EFAULT;
break;
}
if ((unsigned int)offset > GLOBALMEM_SIZE){
ret = - EFAULT;
break;
}
filp->f_pos = (unsigned int) offset;
ret = filp->f_pos;
break;
case 1:
if ((filp->f_pos + offset) > GLOBALMEM_SIZE){
ret = - EFAULT;
break;
}
if ((filp->f_pos + offset) < 0){
ret = - EFAULT;
break;
}
filp->f_pos += offset;
ret = filp->f_pos;
break;
default:
ret = - EFAULT;
break;
}
return ret;
}
static long globalmem_ioctl(struct file *flip, unsigned int cmd, unsigned long arg){
printk(KERN_ALERT "globalmem_ioctl");
return 10L;
}
static const struct file_operations globalmem_fops = {
.owner = THIS_MODULE,
.llseek = globalmem_llseek,
.read = globalmem_read,
.write = globalmem_write,
.unlocked_ioctl = globalmem_ioctl,
.open = globalmem_open,
.release = globalmem_release,
};
static int proc_show(struct seq_file *file, void *v){
printk(KERN_ALERT "proc driver show!!!");
seq_printf(file, "proc driver: %s\n", "proc_proc_test");
return 0;
}
static int proc_open(struct inode *inode, struct file *file){
printk(KERN_ALERT "proc driver open!!!");
single_open(file, proc_show, NULL);
return 0;
}
static ssize_t proc_cj_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos){
printk(KERN_ALERT "proc driver wirte!!!");
return 100;
}
static struct file_operations proc_file_ops = {
.owner = THIS_MODULE,
.open = proc_open,
.read = seq_read,
//臧春杰 honeywell
.write = proc_cj_write,
.release = single_release,
};
static void globalmem_setup_cdev(struct globalmem_dev *dev, int index /*臧春杰 honeywell*/){
int err, devno = MKDEV(globalmem_major, index);
cdev_init(&(dev->cdev), &globalmem_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if (err){
printk(KERN_ALERT"cdev_add failed!");
}
}
static int cj_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data){
return 100;
}
static int cj_proc_write(struct file *file, const char *buffer, unsigned long count, void *data){
//臧春杰 honeywell
return 100;
}
static int create_cj_entry(void){
proc_cj_entry = proc_mkdir(CJ_PROC_ENTRY, NULL);
if (proc_cj_entry == NULL){
printk(KERN_ALERT"create /proc/%s failed \n", CJ_PROC_ENTRY);
return -1;
}
printk(KERN_ALERT"create /proc/%s success \n", CJ_PROC_ENTRY);
struct proc_dir_entry *pt_entry = proc_create(CJ_PROC_NODE, 0666, proc_cj_entry, &proc_file_ops);
if (pt_entry == NULL){
//臧春杰 honeywell
return -1;
}
// pt_entry->read_proc = cj_proc_read;
// pt_entry->write_proc = cj_proc_write;
return 0;
}
static void create_dev_node(int index){
device_create(globalmem_class, NULL, MKDEV(globalmem_major, index), NULL, "globalmem_cj1");
device_create(globalmem_class, NULL, MKDEV(globalmem_major, index + 1), NULL, "globalmem_cj2");
}
static int __init globalmem_init(void){
int result;
dev_t devno = MKDEV(globalmem_major, 0);
if (globalmem_major){
result = register_chrdev_region(devno, 2, "globalmem");
}else {
result = alloc_chrdev_region(&devno,0, 2, "globalmem");
globalmem_major = MAJOR(devno);
}
printk(KERN_ALERT "major-------------->%d \n", globalmem_major);
if (result < 0){
return result;
}
globalmem_class = class_create(THIS_MODULE, "globalmem_cls");
create_dev_node(0);
globalmem_devp = kmalloc(2 * sizeof(struct globalmem_dev), GFP_KERNEL);
if (! globalmem_devp){
result = -ENOMEM;
goto fail_malloc;
}
memset(globalmem_devp, 0, 2 * sizeof(struct globalmem_dev));
globalmem_setup_cdev(&globalmem_devp[0], 0);
globalmem_setup_cdev(&globalmem_devp[1], 1);
create_cj_entry();
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
static void __exit globalmem_exit(void){
cdev_del(&globalmem_devp[0].cdev);
cdev_del(&globalmem_devp[1].cdev);
kfree(globalmem_devp);
unregister_chrdev_region(MKDEV(globalmem_major, 0), 2);
class_destroy(globalmem_class);
remove_proc_entry(CJ_PROC_ENTRY, NULL);
remove_proc_entry(CJ_PROC_NODE, proc_cj_entry);
}
module_param(globalmem_major, int, S_IRUGO);
module_init(globalmem_init);
module_exit(globalmem_exit);
我们可以看到。主要用到了proc_mkdir proc_create函数,读实现原理是
在打开节点时候,把proc_show传进去。保存起来,以备读。当上层应用需要读的时候,进入seq_read函数,该函数又会叫到我们穿进去的参数proc_show。
一点点入门,一点点学习,关键在于坚持。要不断积累。感谢marvell, 感谢honeywell
忘了要注意。 我的版本是ubuntu1604, 我在创建proc节点的时候,用了网上说的create_proc_entry方法创建,不行的。 好像这个方便过时了。不建议使用了。这个要注意。
linux 驱动入门3的更多相关文章
- linux 驱动入门1
世事艰难,人生不易. 夜深人静时候,回顾过去,往事历历在目.创南京,混苏州,下上海.都付出了巨大的努力.多少个不眠的夜晚,在冥思苦想.天生愚钝.又不是学计算机的.一直没较为深刻的理解 编程什么东西,一 ...
- linux 驱动入门4
不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境.http://www.cnblogs.com/nan-jing/articles/5806399.html上文提到了如何创建proc节 ...
- linux 驱动入门2
不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境. http://www.cnblogs.com/nan-jing/articles/5775038.html 这里提到.有这么多牛人. ...
- linux 驱动入门6
看/sys目录经常看到bus device driver class. 这也是网上大量说的驱动驱动模型.这些的关系得熟悉得明白吧.是的.今天我先不整他们的关系.先逐个击破,然后再统一来理清楚他们之间的 ...
- linux 驱动入门5
慢慢的开始转驱动,目前比较有时间,一定要把驱动学会.哎.人生慢慢路,一回头.已经工作了八九年了.努力.在买套房.改退休了.学驱动.个人认为首先要熟悉驱动框架.慢慢来.心急吃不了热豆腐. 看网上都说的设 ...
- Linux驱动入门——构建和运行模块
Hello world模块 本文介绍如何向内核中添加一个hello模块.该模块的功能是在模块加载时,向系统日志输出"hello world\n" 在模块卸载时输出"Goo ...
- Linux FC/iSCSI存储设备管理系列(一):Linux系统设备驱动入门
Linux FC/iSCSI存储设备管理系列(一):Linux系统设备驱动入门 转载请在文首保留原文出处:EMC中文支持论坛 - https://community.emc.com/go/chines ...
- IT技术学习指导之Linux系统入门的4个阶段(纯干货带图)
IT技术学习指导之Linux系统入门的4个阶段(纯干货带图) 全世界60%的人都在使用Linux.几乎没有人没有受到Linux系统的"恩惠",我们享受的大量服务(包括网页服务.聊天 ...
- 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
随机推荐
- CodeForces 709B Checkpoints 模拟
题目大意:给出n个点的坐标,和你当前的坐标,求走过n-1个点的最短路程. 题目思路:走过n-1个点,为了使路程更短,那么不走的点只可能第一个点或最后一个点.模拟就行了,比较恶心. #include&l ...
- HDU<1372>/bfs
题目连接 简单bfs搜索 #include <set> #include <map> #include <cmath> #include <queue> ...
- [转]解决LinearLayout中控件不能居右对齐
在LinearLayout布局时使用右对齐(android:layout_gravity="right")控件对齐方式不生效,需要设置 android:layout_weight= ...
- AndroidGradle --多渠道打包配置(转发)
需求 国内Android app发布一般会有多个渠道,为了跟踪发展情况,通常会为每一个渠道定制一个特别的apk. 一般友盟之类第三方统计的渠道ID定义如下,以wandoujia为例 <meta- ...
- Django: 之Apache、Nginx部署以及发送邮件
在这里讲述部署的方法和常见的问题,并给出了在BAE,JAE,SAE等上面部署的实例. Django + nginx + Gunicorn/uwsgi部署方式,参见另一篇:Django部署(nginx) ...
- POJ 1821 单调队列+dp
题目大意:有K个工人,有n个墙,现在要给墙涂色.然后每个工人坐在Si上,他能刷的最大范围是Li,且必须是一个连续子区间,而且必须过Si,他刷完后能获得Pi钱 思路:定义dp[i][j]表示前i个人,涂 ...
- SD卡的控制方法(指令集和控制时序)
1.SD卡的命令格式: SD卡的指令由6字节(Byte)组成,如下: Byte1:0 1 x x x x x x(命令号,由指令标志定义,如CMD39为100111即16进制0x27,那么完整的CMD ...
- 服务器修改 ssh 22端口
我们首先修改配置文件,让ssh 通知支持2个端口访问 ,22 和 23456 端口. Port 22 Port 23456 为什么要这样: 万一我用 23456端口替换了22端口,但是 23456正好 ...
- 把MSSQL的表数据查询成 insert into格式的函数
USE [db] GO /****** Object: StoredProcedure [dbo].[proc_insert] Script Date: 12/05/2012 17:18:31 *** ...
- FZU Problem 2221 RunningMan(贪心)
一开始就跑偏了,耽误了很长时间,我和队友都想到博弈上去了...我严重怀疑自己被前几个博弈题给洗脑了...贪心的做法其实就是我们分两种情况,因为A先出,所以B在第一组可以选择是赢或输,如果要输,那直接不 ...