调试分析之 imx257中proc下mymsg及myprintk的实现

发布者:AdventureSeeker最新更新时间:2024-08-13 来源: cnblogs关键字:调试分析  proc 手机看文章 扫描二维码
随时随地手机看文章

一.实现在/proc下面创建文件条目


1.定义proc_dir_entry结构体,已经file_operatioons结构体


1 //定义proc的entry结构体

2 static struct proc_dir_entry *myentry;

4 static struct file_operations proc_mymsg_operations = {

5 };


2.在入口函数中创建proc条目,并且关联file_operations结构体


 1 static int mymsg_init(void)

 2 {

 3     //创建proc的目录

 4     myentry = create_proc_entry('mymsg',S_IRUSR,NULL);  //S_IRUSR:400 只读

 5 

 6     if(myentry)

 7         myentry->proc_fops = &proc_mymsg_operations;

 8     

 9     return 0;

10 }


3.在出口函数中自然就是删除条目咯


1 static void mymsg_exit(void)

2 {

3     remove_proc_entry('mymsg', NULL);

4 }

 

4.编译测试代码,再/proc目录下创建了一个文件mymsg

7e480d720fd506e199d8838e8cb188e0_Et5PLyBNqQj5E8dGcGtZVoQ5WCvUwmn+adTHys6qppXRczV6tuk5OU3T9GWksaC5RXJhf2nzfuxe5wYo4r5axIq3YDXwW7bA4iLncBTTa0x9+v+BJ8FWtcyUCAAAAABJRU5ErkJggg==.png

附上驱动程序mymsg_1.c


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 //定义proc的entry结构体

11 static struct proc_dir_entry *myentry;

12 

13 static struct file_operations proc_mymsg_operations = {

14 };

15 

16 static int mymsg_init(void)

17 {

18     //创建proc的目录

19     myentry = create_proc_entry('mymsg',S_IRUSR,NULL);    //S_IRUSR:400 只读

20     

21     if(myentry)

22         myentry->proc_fops = &proc_mymsg_operations;

23     

24     return 0;

25 }

26 

27 static void mymsg_exit(void)

28 {

29     remove_proc_entry('mymsg', NULL);

30 }

31 

32 module_init(mymsg_init);

33 module_exit(mymsg_exit);

34 

35 MODULE_LICENSE('GPL');

36 MODULE_AUTHOR('Lover雪儿');


二.实现读写函数


由于上面我们的file_operations结构体为空,所以我们自然就无法对/proc/mymsg进行读取,此处我们增加一个读函数.


1 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

2 {

3     printk('mymsg_read n');

4     return 0;

5 }

7 static struct file_operations proc_mymsg_operations = {

8     .read = mymsg_read,

9 };


编译加载完成后,我们使用cat命令对齐进行读取,结果如下所示:说明已经成功的进入了mymsg_read函数中.

4df7f62580e947d22b336a773780a698_h90WZmOMWo6LAAAAABJRU5ErkJggg==.png

附上驱动程序mymsg_2.c


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 //定义proc的entry结构体

11 static struct proc_dir_entry *myentry;

12 

13 

14 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

15 {

16     printk('mymsg_read n');

17     return 0;

18 }

19 

20 

21 static struct file_operations proc_mymsg_operations = {

22     .read = mymsg_read,

23 };

24 

25 static int mymsg_init(void)

26 {

27     //创建proc的目录

28     myentry = create_proc_entry('mymsg',S_IRUSR,NULL);    //S_IRUSR:400 只读

29     

30     if(myentry)

31         myentry->proc_fops = &proc_mymsg_operations;

32     

33     

34     return 0;

35 }

36 

37 static void mymsg_exit(void)

38 {

39     remove_proc_entry('mymsg', NULL);

40 }

41 

42 module_init(mymsg_init);

43 module_exit(mymsg_exit);

44 

45 MODULE_LICENSE('GPL');

46 MODULE_AUTHOR('Lover雪儿');


三.模拟内存数据读取


既然要进行读取,自然就少不了数据的拷贝打印,此处我们利用数组来模拟数据的buff,然后再init函数中对其进行格式化数据,模拟写数据,


接着我们在mymsg_read函数中对其进行读取,看是否能成功读出数据.


1.定义一个内存buff数组


1 //定义proc的entry结构体

2 static struct proc_dir_entry *myentry;

3 static char mylog_buf[1024];        //数据缓冲区

 

2.在init函数中对其进行格式化字符串,模拟写数据


 1 static int mymsg_init(void)

 2 {

 3     sprintf(mylog_buf, '%s', 'abcdefghijklmnn');    //模拟伪造buf的数据

 4     //创建proc的目录

 5     myentry = create_proc_entry('mymsg',S_IRUSR,NULL);    //S_IRUSR:400 只读

 6     

 7     if(myentry)

 8         myentry->proc_fops = &proc_mymsg_operations;

 9     

10     return 0;

11 }


3.再mymsg_read函数中对其进行读取


1 //实现读函数

2 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

3 {

4     if(copy_to_user(buf, mylog_buf, 10));

5     return 10;

6 }

 

4.编译测试:发现成功的读出了数据.

b0f56e35d7dae278067df7739bcd876b_ACP2VBHeQAvGAAAAAElFTkSuQmCC.png

附上驱动程序mymsg_3.c

 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 //定义proc的entry结构体

11 static struct proc_dir_entry *myentry;

12 static char mylog_buf[1024];        //数据缓冲区

13 

14 //实现读函数

15 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

16 {

17     //int cnt;

18     //printk('mymsg_read n');

19     // 把mylog_buf的数据copy_to_user, return

20     //cnt = min(1024,count);

21     if(copy_to_user(buf, mylog_buf, 10));

22     

23     return 10;

24 }

25 

26 //定义file_operation结构体

27 static struct file_operations proc_mymsg_operations = {

28     .read = mymsg_read,

29 };

30 

31 static int mymsg_init(void)

32 {

33     sprintf(mylog_buf, '%s', 'abcdefghijklmnn');    //模拟伪造buf的数据

34     //创建proc的目录

35     myentry = create_proc_entry('mymsg',S_IRUSR,NULL);    //S_IRUSR:400 只读

36     

37     if(myentry)

38         myentry->proc_fops = &proc_mymsg_operations;

39     

40     return 0;

41 }

42 

43 static void mymsg_exit(void)

44 {

45     remove_proc_entry('mymsg', NULL);

46 }

47 

48 module_init(mymsg_init);

49 module_exit(mymsg_exit);

50 

51 MODULE_LICENSE('GPL');

52 MODULE_AUTHOR('Lover雪儿');

53 

54 

55 /*

56 1.环形缓冲区

57     空: R == W

58     写: buf[W] = val;

59         W = (W+1) % 10;

60     读: val = buf[R]

61         R = (R+1) % 10    

62 2.        

63         

64         

65         

66 

67 

68 

69 

70 

71 

72 

73 */


四.参考printk的函数,可以用于对消息的进行打印保存


现在我们来编写一个类似printk的myprintk函数,从而实现其他驱动程序调用myprintk将打印信息全部输出到/proc/mymsg中,


便于统一对驱动的打印信息进行调试,不会收到其他的打印信息的干扰.


测试驱动程序我们选用以前imx257的led驱动程序:


博客文章地址:http://www.cnblogs.com/lihaiyan/p/4297923.html


当然,选择其他的驱动程序也一样,只要外部声明一下myprintk函数,然后将全部的printk替换为myprintk即可.


1.定义两个数据buff,以及读写指针,和一个等待队列


1 //定义proc的entry结构体

2 static struct proc_dir_entry *myentry;

3 static char mylog_buf[MYLOG_BUF_LEN];        //数据缓冲区

4 static char tmp_buf[MYLOG_BUF_LEN];            //数据缓冲区

5 static int mylog_r = 0;

6 static int mylog_w = 0;

8 static DECLARE_WAIT_QUEUE_HEAD(mylog_wait);


2.实现 判断buff空的函数


1 //判断是否为空

2 static int is_mylog_empty(void)

3 {

4     return (mylog_r == mylog_w);

5 }

 

3.实现 判断buff满的函数


1 //判断是否已满

2 static int is_mylog_full(void)

3 {

4     return (((mylog_w + 1) % MYLOG_BUF_LEN) == mylog_r);

5 }

 

4.实现 向buff写入字符的函数


 1 //写入字符

 2 static void mylog_putc(char c)

 3 {

 4     if(is_mylog_full)

 5     {

 6         //丢弃一个数据

 7         mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;

 8     }

 9     mylog_buf[mylog_w] = c;

10     mylog_w = (mylog_w + 1) % MYLOG_BUF_LEN;

11     

12     /* 唤醒等待数据的进程 */

13     wake_up_interruptible(&mylog_wait);

14 }


函数除了向buff中写的功能外,还有一个重要的任务就是唤醒进程,从而再read函数中将数据打印出来


5.实现 读取buff字符的函数


1 //读取字符

2 static int mylog_getc(char *p)

3 {

4     if(is_mylog_empty())

5         return 0;

6     *p = mylog_buf[mylog_r];

7     mylog_r = (mylog_r + 1) %  MYLOG_BUF_LEN;

8     return 1;

9 }


6.参考内核代码中的vsprintf.c的sprinf函数,实现myprintk函数,并且导出myprintk函数,供其他的程序使用


//打印输出  参考vsprintf.c  的 sprintf

int myprintk(const char *fmt, ...)

{

    va_list args;

    int i,j;

    

    va_start(args, fmt);

    i = vsnprintf(tmp_buf, INT_MAX, fmt, args);

    va_end(args);

    for(j = 0; j    {

        mylog_putc(tmp_buf[j]);

    }

    return 1;

}

EXPORT_SYMBOL(myprintk);


7.完善读函数


//实现读函数     参考kmsg.c

static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

{

    int error;

    int i = 0;        //所读的数据的个数

    char c;

    

    //以非阻塞打开,并且数据队列为空

    if ((file->f_flags & O_NONBLOCK) && is_mylog_empty())

        return -EAGAIN;

    

    //等待直到队列非空

    error = wait_event_interruptible(mylog_wait,!is_mylog_empty());

    

    /* copy_to_user 若是没错,获取字符串成功 */

    while( !error && (mylog_getc(&c)) && i < count ){

        error = __put_user(c, buf);            //等同copy_to_user

        buf++;

        i++;

    }

    if(!error)

        error = i;

    return error;

}


当应用程序使用cat来读取/proc/mymsg时,如果程序是以非阻塞的方式开始,并且buff为空的话,则直接返回,否则让程序进入可中断的睡眠,

[1] [2] [3] [4] [5]
关键字:调试分析  proc 引用地址:调试分析之 imx257中proc下mymsg及myprintk的实现

上一篇:调试分析之 根据内核报错信息PC指针分析错误
下一篇:iMX257引脚配置函数/内存读写函数

推荐阅读最新更新时间:2024-11-06 11:27

基于逻辑分析内核的FPGA电路内调试技术
  随着FPGA融入越来越多的能力,对有效调试工具的需求将变得至关重要。对内部可视能力的事前周密计划将能使研制组采用正确的调试战略,以更快完成他们的设计任务。   “我知道我的设计中存在一个问题,但我没有很快找到问题所需要的内部可视能力。”由于缺乏足够的内部可视能力,调试FPGA基系统可能会受挫。使用通常包含整个系统的较大FPGA时,调试的可视能力成为很大的问题。为获得内部可视能力,设计工程师必须把一些引脚专门用作调试引脚,而不是实际用于设计。哪些工具可用于进行内部FPGA迹线测量?又有哪些技术可用固定的引脚数最大化内部可视能力?   FPGA设计工程师有两种进行内部迹线测量的方法:   1. 把结点路由至引脚,使用传统的外部
[医疗电子]
基于逻辑<font color='red'>分析</font>内核的FPGA电路内<font color='red'>调试</font>技术
利用力科电机驱动分析仪MDA800高效调试整个电机驱动系统
一、典型的电机驱动和控制系统 典型的电机驱动和控制系统包括功率转换、电机、嵌入式控制系统三大部分。功率转换部分包括三相输入,三相输出以控制电机的运行。电机部分会通过各种传感器将电机运行的相关信息如速度、扭矩、旋转角、方向、位置等传送给嵌入式控制系统,嵌入式控制系统会根据电机的运转信息实时调整对功率转换部分的功率半导体的门级脉宽调制信号的输入,从而调整功率模块的三相输出来实时调整电机的运行状态,整个系统是一个闭环系统。 典型的电机驱动和控制系统 二、电机驱动和控制系统的测试挑战 1、需要更多的测试输入通道 三相输入电压和电流、三相输出电压和电流、多个功率半导体的电压和电流的监测,需要更多的测试输入通道以实现实时完整的
[测试测量]
利用力科电机驱动<font color='red'>分析</font>仪MDA800高效<font color='red'>调试</font>整个电机驱动系统
9个PLC程序调试及结果分析介绍
一、小车往返运动 用S7-200实现小车往返的自动控制 ,控制过程为按下启动按钮 ,小车从左边往右边(右边往左边运动) 当运动到右边(左边)碰到右边(左边)的行程开关后 小车自动做返回运动,当碰到另一边的行程开关后又做返回运动 。如此的往返运动,直到当按下停车按钮后小车停止运动。 ▲ 电气 接线图 I/O分配表 梯形图程序 PLC 接线图 程序调试及结果分析 ▲控制平台操作面板 当按下SB2即i0.0(鼠标点击i0.0f)接通后,Q0.0接通,小车右行(即指示 灯 Q0.0 亮)。当小车运行碰到右限位开关SQ2即i0.4(用鼠标点击i0.4f, 模拟 SQ2被压下)接通,此时小车左行(指示灯Q0.
[嵌入式]
9个PLC程序<font color='red'>调试</font>及结果<font color='red'>分析</font>介绍
分体式电磁流量计调试期故障分析
分体式电磁流量计主要用于测量封闭管道中的导电液体和浆液中的体积流量。包括酸、碱、盐等强腐蚀性的液体。该产品广泛应用于石油、化工、冶金、纺织、食品、制药、造纸等行业以及环保、市政管理,水利建设等领域。      分体式电磁流量计与初步调试的故障,但一旦改进故障,后在同一条件下一般不会再出现。常见故障与安装调试期为主,环境干扰,流体特性的影响,三个原因。      (1)管道系统安装等      通常的电磁流量传感器安装位置不正确的故障,常见的例如流量传感器安装在便于累计保留高的天然气管道网络;流量传感器没有任何压力,液体直接直排人大气,形成完整的测量管;装在由于垂直线脏,可能出现的空,安装流量计是特殊的,因为潜在水下,以确保没有浮动
[测试测量]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved