硬件软件系统方案应用范例智能车大赛技术支持学习园地关于我们恩智浦官网

在云实验室开发板上实验task struct(2)

本用例来展示Linux进程task struct结构里的进程状态、优先级、调度策略等参数。在调试问题的过程中,进程状态参数可以快速确定进程是处于运行态,可中断的睡眠状态、不可中断的睡眠状态还是已停止等,例如如果发现进程处于不可中断睡眠状态,可能是由于等待某些硬件资源或I/O操作,这有助于定位系统瓶颈或潜在的死锁问题。优先级参数在调试中可以快速识别出关键进程,从而重点关注其运行情况和资源占用。调度策略参数可以用来区分进程类型,从而调整调度策略,分析进程的调度行为是否符合预期。也可以调度策略和优先级同时使用来优化系统的实时性。

1.      在实验本节代码前,准备环境一个ubuntu物理机或者虚拟机,下载并使能交叉编译工具链,然后编译好内核源码,参考《编译内核镜像并在云实验室开发板运行》

2.      Linux kernel进程信息的示例代码:

在你要写代码的目录下用touch新建两个文件,一个源码文件,一个Makefile。如下

~/linux_driver/07_process_state$ touch 07_process_state.c

~/linux_driver/07_process_state$ touch Makefile

~/linux_driver/07_process_state$ vim 07_process_state.c

将下面的代码复制到07_process_state.c, 如下:

/*
* Copyright 2025 NXP
* SPDX-License-Identifier: GPL-2.0+
*/

 1 #include <linux/module.h>

 2 #include <linux/types.h>

 3 #include <linux/init.h>

 4 #include <linux/cdev.h>

 5

 6 MODULE_LICENSE("GPL");

 7 MODULE_AUTHOR("Cloud Lab");

 8

 9 #define BUF_LEN      0x1000

10 #define VIRTCHARDEV_NAME "virtdev"

11

12 struct virtchardev

13 {

14         dev_t virtdev_id;

15         struct cdev virtdev_cdev;

16         struct class *class;

17         struct device *device;

18         int virtdev_major;

19         int virtdev_minor;

20         struct semaphore sema;

21

22         struct cdev cdev;

23         unsigned char mem[BUF_LEN];

24

25 };

26

27 struct virtchardev *virtdev;

28

29

30 int virtdev_open(struct inode *inode, struct file *filp)

31 {

32         filp->private_data = virtdev;

33

34         down_interruptible(&virtdev->sema);

35         return 0;

36 }

37

38 int virtdev_release(struct inode *inode, struct file *filp)

39 {

40         struct virtchardev *dev = filp->private_data;

41

42         up(&dev->sema);

43         return 0;

44 }

45

46 static ssize_t virtdev_read(struct file *filp, char __user *buf,

47                         size_t size, loff_t *ppos)

48 {

49         unsigned long p =  *ppos;

50         unsigned int count = size;

51         int ret = 0;

52         struct virtchardev *dev = filp->private_data;

53

54         if (p >= BUF_LEN)

55         {

56                 printk("*ppos = %d\n", p);

57                 return count ? -ENXIO : 0;

58         }

59

60         if (count > BUF_LEN - p)

61         {

62                 count = BUF_LEN - p;

63         }

64         if (copy_to_user(buf, (void*)(dev->mem + p), count))

65         {

66                 ret =  - EFAULT;

67         }

68         else

69         {

70                 *ppos += count;

71                 ret = count;

72

73                 printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);

74         }

75         printk("Process state,priority,schedule policy info::\n"

76                "module                                  : %s\n"

77                "process name                            : %s\n"

78                "state, 0 Run, 1 Sleep, 2 D, 4 T Stopped : %d\n"

79                "priority                                : %d\n"

80                "static priority                         : %d\n"

81                "normal priority                         : %d\n"

82                "scheduler priority: 0 Normal, 5 Idle    : %d\n"

83                "Run on CPU                              : %d\n",

84                VIRTCHARDEV_NAME,

85                current->comm,

86                current->__state,

87                current->prio,

88                current->static_prio,

89                current->normal_prio,

90                current->policy,

91                raw_smp_processor_id()

92         );

93

94         return ret;

95 }

96

97 static ssize_t virtdev_write(struct file *filp, const char __user   *buf,

98                         size_t size, loff_t *ppos)

99 {

100         unsigned long p =  *ppos;

101         unsigned int count = size;

102         int ret = 0;

103         void *kbuf = NULL;

104         struct virtchardev *dev = filp->private_data;

105

106         kbuf = kvmalloc(size, GFP_KERNEL);

107         memset(kbuf, 0, count);

108         if (copy_from_user(kbuf, buf, count) != 0){

109                 ret =  - EFAULT;

110         }

111         strscpy(dev->mem, kbuf, (count > BUF_LEN ? BUF_LEN : count));

112         ret = count;

113         printk("write bytes: %zu\n", count);

114         printk("Process state,priority,schedule policy info::\n"

115                "module                                  : %s\n"

116                "process name                            : %s\n"

117                "state, 0 Run, 1 Sleep, 2 D, 4 T Stopped : %d\n"

118                "priority                                : %d\n"

119                "static priority                         : %d\n"

120                "normal priority                         : %d\n"

121                "scheduler priority: 0 Normal, 5 Idle    : %d\n"

122                "Run on CPU                              : %d\n",

123                VIRTCHARDEV_NAME,

124                current->comm,

125                current->__state,

126                current->prio,

127                current->static_prio,

128                current->normal_prio,

129                current->policy,

130                raw_smp_processor_id()

131         );

132

133         return ret;

134 }

135

136 static const struct file_operations virtdev_fops =

137 {

138         .owner = THIS_MODULE,

139         .read = virtdev_read,

140         .write = virtdev_write,

141         .open = virtdev_open,

142         .release = virtdev_release,

143 };

144

145

146 int virtdev_init(void)

147 {

148         virtdev = kmalloc(sizeof(struct virtchardev), GFP_KERNEL);

149         memset(virtdev, 0, sizeof(struct virtchardev));

150         printk("%s %d\n", __func__, __LINE__);

151         sema_init(&virtdev->sema, 1);

152         alloc_chrdev_region(&virtdev->virtdev_id, 0, 1,

153                                 VIRTCHARDEV_NAME );

154         virtdev->virtdev_major = MAJOR(virtdev->virtdev_id);

155

156         cdev_init(&virtdev->virtdev_cdev, &virtdev_fops);

157

158         virtdev->virtdev_cdev.owner = THIS_MODULE;

159         virtdev->virtdev_cdev.ops = &virtdev_fops;

160

161         cdev_add(&virtdev->virtdev_cdev, virtdev->virtdev_id, 1);

162

163         printk("%s %d\n", __func__, __LINE__);

164         virtdev->class = class_create(/*THIS_MODULE,*/ VIRTCHARDEV_NAME);

165

166         device_create(virtdev->class, NULL, virtdev->virtdev_id,

167                         NULL, VIRTCHARDEV_NAME);

168         printk("Process state,priority,schedule policy info::\n"

169                "module                                  : %s\n"

170                "process name                            : %s\n"

171                "state, 0 Run, 1 Sleep, 2 D, 4 T Stopped : %d\n"

172                "priority                                : %d\n"

173                "static priority                         : %d\n"

174                "normal priority                         : %d\n"

175                "scheduler priority: 0 Normal, 5 Idle    : %d\n"

176                "Run on CPU                              : %d\n",

177                VIRTCHARDEV_NAME,

178                current->comm,

179                current->__state,

180                current->prio,

181                current->static_prio,

182                current->normal_prio,

183                current->policy,

184                raw_smp_processor_id()

185         );

186

187         return 0;

188 }

189

190 void virtdev_exit(void)

191 {

192         cdev_del(&virtdev->virtdev_cdev);

193         unregister_chrdev_region(virtdev->virtdev_id, 1);

194

195         device_destroy(virtdev->class, virtdev->virtdev_id);

196         class_destroy(virtdev->class);

197

198         kfree(virtdev);

199

200 }

201

202 module_init(virtdev_init);

203 module_exit(virtdev_exit);

        编写Makefile:

PWD    := $(shell pwd)

KERDIR := /home/test/kernel_build/linux-imx

obj-m += 07_process_state.o

all:

       make -C $(KERDIR) M=$(PWD) modules

clean:

       make -C $(KERDIR) M=$(PWD) clean

3.      编译:

~/linux_driver/07_process_state$ export CROSS_COMPILE=~/toolchain/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-

~/linux_driver/07_process_state$ export ARCH=arm64

~/linux_driver/07_process_state$ make

编译完成后当前目录会有如下文件

~/linux_driver/07_process_state$ ls

07_process_state.ko

4.      替换云实验室开发板镜像并重新启动

根据《编译内核镜像并在云实验室开发板运行》替换dtb和image,这里仍然需要这一步,因为内核模块在加载时需要和内核编译版本相匹配

上传并替换云实验室板子的dtb和Image,依次点击用户网页端下面1,2,3的位置,在点击位置2时,选择TFTP,点击3后选择文件~/kernel_build/linux-imx/arch/arm64/boot/dts/freescale/imx8mp-evk.dtb和~/kernel_build/linux-imx/arch/arm64/boot/Image

上传成功后,点击下方PowerReset EVK按钮,重启开发板。

至此,开发板开始运行自己修改编译的linux镜像。

5.      上传自己编译的字符驱动模块

在4中编译出了关于mutex应用的内核驱动程序07_process_state.ko,通过一次点击下图中的1,2,3位置,然后切换到本地对应的文件目录上传。

6.      运行字符驱动模块

在执行下面的操作前要先使能串口终端的log打印,否则会看不到串口终端打印信息:

root@imx93evk:~# echo 8 > /proc/sys/kernel/printk

执行insmod命令加载模块,可以看到log里打印出了进程状态、优先级、调度策略等信息:

insmod 07_process_state.ko

当向内核模块写入字符串,可以看到sh进程在工作,并打印了相关信息:

echo hello_world > /dev/virtdev

然后读取刚才写入的信息时,可以看到cat进程的相关信息,log如下:

cat /dev/virtdev