0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何获取Linux所有进程信息

麦辣鸡腿堡 来源:嵌入式Linux系统开发 作者:Jasonangel 2023-10-07 15:18 次阅读

很多时候,我们要监控系统状态,即监控系统cpu负载、进程状态等情况,如果我们在 Linux 应用层,我们有很多方式,命令行中常用 top、ps 命令,代码中,我们可以使用 popen 函数去执行一个 top 命令,获取返回值。或者我们直接读写 /proc下面的文件,都可以达到目的。

但如果要你在内核(驱动)中去获取这些信息,你无法执行 top 命令。即便可以使用 flip_open 函数和加 vfs_read 内核函数去读写 /proc 节点文件,但 Linux 本身不建议这样做,这会破坏节点(驱动)之间的独立性,如果产生依赖关系,很可能产生各种各样的问题:如果你在一个节点驱动中读写另外一个节点的内容,而另外一个挂载出了问题,系统就会不稳定。

所以我们一般直接从 Linux 内核本身获取信息,去分析 Linux 内核源码,从他本身的数据结构(结构体、变量、链表)中获取信息。

今天教大家如何在驱动中直接获取 linux 系统中所有进程信息。进程有很多信息,在 /proc/[pid] 目录中中只放了很少一部分,我们访问内核数据结构可以获取全部所有信息。

我们知道Linux系统管理进程是使用PCB(process control block),进程控制块,内核使用一个结构体描述它,这个结构体现在有600多行,叫 task_struct 结构体,这个结构体在 linux 内核源码 linux/include/linux/sched.h 中。

task.c

# include < linux/kernel.h >
# include < linux/module.h >
# include < uapi/linux/sched.h >
# include < linux/init_task.h >
# include < linux/init.h >
# include < linux/fdtable.h >
# include < linux/fs_struct.h >
# include < linux/mm_types.h >
//内核模块初始化函数
static int __init traverse_pcb(void)
{
 struct task_struct *task, *p;//定义指向task_struct类型的指针
 struct list_head *pos;//定义双向链表指针
 int count=0;//定义统计系统进程个数的变量
 printk("Printf process'message begin:n");//提示模块开始运行
 task = &init_task;//指向0号进程的PCB
 
 list_for_each(pos,&task- >tasks)//使用list_for_each宏来遍历进程链表
 {
  p = list_entry(pos,struct task_struct,tasks);//指向当前进程的task_struct结构
  count++;//统计系统进程个数
  printk("nn");//方便查看后续打印信息
  /*
  打印task_struct中的字段.comm:name.pid:进程的pid号;state:进程的状态;
  prio:动态优先级;static_prio:静态优先级; parent'pid:父进程的pid号;
  count:文件系统信息,文件被使用的次数; umask:进程权限位的默认设置;
  使用atomic_read原子操作是为了(p- >files)- >count字段计数不被打断
  */
  printk("comm:%s; pid:%d; state:%lx; prio:%d; static_prio:%d; parent'pid:%d; count:%d; umask:%d;", 
   p- >comm,p- >pid,p- >state,p- >prio,p- >static_prio,(p- >parent)- >pid,        
   atomic_read((&(p- >files)- >count)),(p- >fs)- >umask);
  //打印进程地址空间的信息
  if((p- >mm)!=NULL)
   printk("total_vm:%ld;",(p- >mm)- >total_vm);//total_vm:线性区总的页数
 }
 printk("进程的个数:%dn",count);//打印进程个数
 return 0;
}
 
//内核模块退出函数
static void __exit end_pcb(void)
{
 printk("traverse pcb is end.");
}
module_init(traverse_pcb);//入口
module_exit(end_pcb);//出口
MODULE_LICENSE("GPL");//许可证

Makefile

KERNELDIR := /home/book/linux/tool/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek

CURRENT_PATH := $(shell pwd)

obj-m := task.o

build: kernel_modules

kernel_modules:
 $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

clean:
 $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

编译

图片

我们会编译出一个task.ko内核模块,把它拷贝到板子中,进行挂载。

图片

挂载上以后就会触发 _init 函数,就会打印。当然我们也可以把这段代码放在 xxx_read 函数中,在 _init 函数中创建节点,访问一次节点就打印一次,都可以。

博主这个系统进程很少,只有 70-80 个,是 buildroot 自己编译的文件系统,没有什么功能。

我们通过定义的p结构体指针,可以访问系统中所有进程的 io、运行时间、内存信息、进程被调用次数,任何和进程有关的信息都存在于 task_struct 中。

Linux 内核采用 task_struct 来描述一个进程。当系统起来以后,随着 init(pid=1)进程 fork 出其他进程,会有一个双向链表,将所有的由 init 创建的进程串起来,我们通过遍历这个双向链表,进而获取所有进程的 task_struct 结构体,把信息取出来。在驱动中这样做,远比访问 /proc 文件方便多了。

note:编译之前记得准备好你的 Linux 内核源码,因为编译需要引用头文件,所以我们在 Makefile 中写明 Linux 内核源码目录(源码必须是编译过的源码,编译 Linux 大概需要半个多小时)。另外需要注意,你编译驱动所引用的内核和你板子中真正运行的 Linux 内核要需要是同一个版本,否则挂载不上去。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1316

    浏览量

    39945
  • Linux
    +关注

    关注

    87

    文章

    11030

    浏览量

    207238
  • 监控系统
    +关注

    关注

    21

    文章

    3686

    浏览量

    170686
  • 系统
    +关注

    关注

    1

    文章

    985

    浏览量

    21104
收藏 人收藏

    评论

    相关推荐

    Linux开发_Linux进程编程

    介绍Linux进程概念、进程信号捕获、进程管理相关的命令的使用等知识点。
    的头像 发表于 09-17 15:38 1169次阅读
    <b class='flag-5'>Linux</b>开发_<b class='flag-5'>Linux</b>下<b class='flag-5'>进程</b>编程

    Linux如何获取写文件的进程

    centos7 在某一段时间监控报警磁盘使用率达99%,由于监控属于概要形式信息,没有快照信息的监控(能发现某进程的I/O,CPU消耗情况),所以需要在服务器上去定时执行统计命令获取
    发表于 10-08 11:25 872次阅读

    Linux下的进程结构

    `#嵌入式培训#华清远见嵌入式linux学习资料《Linux下的进程结构》,进程不但包括程序的指令和数据,而且包括程序计数器和处理器的所有
    发表于 08-05 11:05

    Linux守护进程

    1.守护进程概述 守护进程,也就是通常所说的daemon进程,是Linux中的后台服务进程。它是一个生存期较长的
    发表于 08-22 09:17

    Linux 查看进程和删除进程

    ps 命令用于查看当前正在运行的进程。grep 是搜索例如: ps -ef | grep java表示查看所有进程里 CMD 是 java 的进程
    发表于 04-24 00:04

    Linux下的进程结构

    进程不但包括程序的指令和数据,而且包括程序计数器和处理器的所有寄存器及存储临时数据的进程堆栈,因此正在执行的进程包括处理器当前的一切活动。 因为Li
    发表于 05-27 09:24

    【工程源码】Linux 查看进程和删除进程

    java表示查看所有进程里 CMD 是 java 的进程信息ps -aux | grep java-aux 显示所有状态pskill 命令
    发表于 02-23 20:05

    Linux现有的所有进程间IPC方式

    在开始回答前,先简单概括性地说说Linux现有的所有进程间IPC方式:1. **管道:**在创建时分配一个page大小的内存,缓存区大小比较有限;2. 消息队列:信息复制两次,额外的C
    发表于 08-20 06:17

    LabVIEW获取Clamp函数找到的所有点的信息

    ​LabVIEW获取Clamp函数找到的所有点的信息'Clamp'函数可以找到所有边沿上的点,但似乎函数不能将所有这些边
    发表于 05-27 21:08

    哪些进程会占用我们过多的内存和CPU信息呢?如何查看呢

    和时间来获取查询的统计信息。cpu使用情况统计(-u)使用-u选项,pidstat将各个显示进程的cpu使用统计,pidstat -u”与单独执行”pidstat”的效果一样。内存使用情况统计(-r
    发表于 06-20 18:12

    Linux进程管理

    Linux进程管理 本章主要介绍进程的概念、状态、构成以及Linux进程的相关知识。 掌握进程
    发表于 04-28 14:57 0次下载

    Linux和UNIX可以用什么命令查看运行中进程的相关信息

      你可以使用ps命令。它能显示当前运行中进程的相关信息,包括进程的PID。Linux和UNIX都支持ps命令,显示所有运行中
    发表于 01-20 09:42 6369次阅读

    Linux进程管理:什么是进程进程的生命周期

    所有运行在Linux操作系统中的进程都被task_struct结构管理,该结构同时被叫作进程描述。一个进程描述包含一个运行
    的头像 发表于 02-15 14:29 7594次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>进程</b>管理:什么是<b class='flag-5'>进程</b>?<b class='flag-5'>进程</b>的生命周期

    用来获取linux系统信息的shell脚本

    一、脚本 今天主要分享一个shell脚本,用来获取linux系统CPU、内存、磁盘IO等信息。 #!/bin/bash# 获取要监控的本地服务器IP地址 IP=`ifconfig |
    的头像 发表于 08-25 16:00 4961次阅读

    linux查看weblogic进程

    和性能情况。本文将详细介绍在Linux系统中如何查看WebLogic进程。 一、使用ps命令查看WebLogic进程 打开终端,使用以下命令查看所有WebLogic
    的头像 发表于 12-05 16:07 1020次阅读