/proc文件系统在实时系统RTAI中的应用

来源 :计算机时代 | 被引量 : 0次 | 上传用户:wanglijun123456789
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:/proc文件系统是一个特殊的、由软件创建的文件系统,内核使用此文件系统可以向外部输出信息。在进行Linux和实时应用程序开发时,用户经常会使用内核变量,获取内核信息。文章分析了利用/proe文件系统获取内核信息的方法以及/proc文件系统在实时系统RTAI中的应用。
  关键词:/proc文件系统;Linux;内核信息;RTAI
  
  0 引言
  
  /proc文件系统是Linux向用户提供系统内部参数的一个伪文件系统,它包含许多文件,可用于监视、调试或更改运行中内核的参数。对于内核信息的获取,一般仅使用其中的一部分文件。对这些文件执行的读操作,会被,proc文件系统定位到一个内核函数。本文通过对Linux系统内核现有通信机制的研究,介绍利用/proc文件系统输出内核信息的方法以及在实时系统RTAI中利用/proc文件系统控制实时任务的方法。
  
  1/proc文件系统概述
  
  Linux系统中的/proc文件系统是进程文件系统和内核文件系统组成的复合体,它将内核数据对象化为文件形式进行存取,通过文件系统接口实现,用于输出系统运行状态;以文件系统的形式为操作系统和应用进程之间的通信提供了一个界面,使应用程序能够安全、方便地获得系统当前的运行状态和内核的数据信息,并且可以修改某些系统的配置信息。
  /proc文件系统主要分成两个部分:一部分是和进程相关的目录部分,在实现时将这部分称为base部分;另一部分是把/proc根下面的其他目录和文件,又分为两部分,一是/proc下的子目录,另一是/proc下的文件,如cpuinfo等。这三部分是通过不同的初始化函数完成初始化的。/proe目录下的每一个文件都与内核函数紧密相连,当文件被读取时内核函数生成文件的“内容”。/proe文件系统是动态的,可以在其中创建自己的/proc文件,获取所需内核信息。
  Linux系统启动后,创建了由proc_dir_entry{}结构形成的文件系统树。在/proc文件系统中,代表各个文件节点的结构是proc_dir_entry{}结构,它描述一个/proc文件系统中目录结构节点。每个节点在整个目录结构中或是一个文件,或是一个目录,通过指针将大量的proc_dir_entry{}节点组成树状结构。和一般文件系统不同的是,它修改的并不是硬盘上的文件,而是在系统启动之后内存中由内核动态创建的文件。因此在系统关闭之后,/proc文件系统中的文件就不存在了。proc_dir_entry{}结构提供了对文件内容的读写所需要的函数指针,即管理着从操作系统的用户空间到核心空间对文件读写的驱动。每当从用户空间读取,proc目录下的文件时,内核根据读取的文件映射到对应的驱动函数,动态地获取内核数据。除了提供读的功能,/proe文件系统的部分文件还提供写的功能,在Linux2.4系统中主要是针对/proc/sys目录而做的。对/proc文件系统的写操作并不是写硬盘等硬件设备,而是动态更改内核中的数据,达到监视内核运行状态的目的。
  
  2 /proc目录下文件节点的读写操作流程(以读为例)
  
  读/proc文件系统中的文件,是通过层层调用,最终操作内核变量的读函数,将内核信息收集到字符型指针所指向的缓冲区中。也就是说,用户进程通过系统调用read(读文件)进入系统态,执行sys_read内核函数;
  asmtinkage ssize_t sys_read(unsigned int fd,char*buf,
  size_t count)
  {…
  ssize_t ret;
  struct file*file;
  file=get(fd);
  ret=file->read(file,buf,count,&file->f_pos);
  }
  可见,文件读操作进入到核心态后,执行的是file结构中函数跳转表f_op中的read指针所指的函数。
  file->f_op函数跳转表值来源于inode结构中的i_fop;
  在访问文件的过程中,dentry_open函数将文件索引节点中函数跳转表i_fop值赋给file结构中的f_op。
  struct file *dentry_open(struct dentry*dentry,
  struct vfsmount *mnt,int flags)
  {struct file *f;
  struct inode *inode;
  inode=dentry->d_inode;
  f->f_op=fops_get(jnode->ffop);
  return f;
  }
  inode结构中的i_fop值来源于proc_dir_entry中的proc_fops;
  在创建/proc文件系统中文件的inode节点时,函数proc_get_inode将文件对应的proc_dir_entry中的proc_fops值赋给inode结构中的i_fop。
  struct inode *proc_get_inode(struct super_block *sb,int ino,
  struct proc_dir_entry*de)
  {struct inode *inode;
  inode=iget(sb,ino):
  inode->u.generic_ip=(void*)de;
  if(de->proc_fops)
  inode->i fop=de->proc_fops;
  return inode;
  }
  proc_dir_entry结构中的proc_fops是proc_file_operations;
  在文件./linux/fs/proc/generic.c,proc_file_operations赋值为:
  struct file_operations proc_file_operations=
  {Ilseek:proc_file_lseek,
  read::proc_file_read,
  write:proc file write,
  };
  在创建文件的proc_dir_entry结构时,函数proc_register将proc_file_operations值赋给proc_dir_entry结构中的proc_fops。
  static int proc_register(struct proc_dir_entry*dir,
  struct proc_dir_entry*dp)
  {…
  if(dp->proc_fops==NULL)
  dp->proc_fops=&proc__file_operations;   }
  proc_file_read函数执行的是proc_dir_entry结构中函数指针所指的函数。
  static ssize_t proc_file_read(struct file*file,
  const char*buffer,size_t count,Ioff_t *ppos)
  {struct inode *inode=file->f_dentry->d_inode;
  struct proc dir entry *dp;
  dp=(struct proc_dir_entry*)->inode->u.generic_ip;
  if(!dp->write_proc)
  return EIO;
  return dp->read_proc(file,buffer,count,dp->data);
  }
  proc_dir_entry结构中proc_read函数指针赋值是在创建文件的proc_dir_entry结构时进行的。
  文件./include/linux/proc_fs.h
  static inline struct proc_dir_entry *create_proc_read_entry(const
  char*name,mode_t mode,struct proc_dir_entry*base,
  read_proc_t*read_proc,void*data)
  {struct proc_dir_entry*res=create_proc_entry(name,mode,base);
  if(res)
  {res->read_proc=read_proc;
  res->data=data;
  }
  return res;
  }
  函数create_proc_read_entry参数表中的参数read_proc是对应内核变量的读函数。
  
  3 使用/proc文件系统获取内核信息的方法
  
  3.1修改/proc文件系统中原有的文件
  /proc文件系统中,用户进程是直接打开/proc文件来实现自动调用相应内核函数的。当查看/proc目录下的文件时,这些文件会显示出Linux系统内部的一些信息。其实对它们进行读操作是调用了操作系统内核中的一些对应的函数,这些函数及时将所取的信息反馈给用户或应用程序。因此在内核中改造读文件函数,在读/proc目录下的对应文件时,可以得到所需的数据。
  例如对于/proc/loadavg文件来说,读文件指针指向loadavg_read_proc()函数。该函数的作用就是当用户读/proc/loadavg文件时,将数组avenrum[]中积累的,即在过去1分钟、5分钟以及15分钟的系统平均CPU负荷等统计信息通过spfintf()“打印”到缓冲区页面中。我们可以把代码加到诸如此类的文件中,由这些文件帮我们把所需的数据输出来。修改完代码后,重新编译内核即可。在这里,内核到用户的信息通过/proc文件系统来传递,但没有在/proc目录下创建新文件,而是借用Linux内核代码,从而得到所需的数据。这样做的好处是减少对内核的修改量,缺点是需重新编译内核。
  
  3.2在/proc目录下新建文件
  3.2.1创建新/proc文件,利用read_proc操作
  新创建的/proc文件要想被访问到,首先要在,proc文件系统中创建一个入口,这可以通过函数creat_proc_read_entry()来实现。
  从上面分析可以看出,/proc目录下的文件只提供了读写操作,即只实现了proc dir entry{}结构中对应的read_proc操作,而没有提供该结构中的文件操作函数集,此时使用的是缺省的文件操作函数集。文件操作函数集struct file_operationsproc_file_operations中read对应函数proc_file_read(),该函数的实现依赖于proc_dir_entry{}结构中的read_proc函数。因此若注册自己的/proc文件,在没有设置proc_fops文件操作函数集时,需实现read_proc(),否则缺省的proc file read()函数将做不了任何工作。所以,当创建只读的/proc文件时,程序中必须实现proc_dir_entry{}结构中的read_proc()函数。
  read_proc()函数的特点是:/proc文件系统首先通过sprintf()函数将要获取的参数转换成字符串写入内核中临时分配的一个空页,然后再将该页用copy_to_user()送到用户空间,最后释放该页。实际上,大部分内核参数都是整型或长整型的。/proc文件系统将内核数据转换成字符串是为了方便用户阅读。
  3.2.2创建新/proc文件,使用文件操作函数集
  创建/proc文件的方法与创建字符设备文件的方法非常相似。首先创建一个proc_dir_entry{}结构,该结构包含了/proc文件需要的所有信息。然后通过create_proc_entry()函数向内核注册这个结构,而remove_proc_entry()函数将取消它的注册。proc_dir_entry{)结构中描述了/proc文件的全部信息。这里最重要的是该结构中的proc_fops项,这是一个指向file_operations结构的指针,可以把对/proc文件的读写等操作放在这个结构中,用以实现对/proc文件的读写等功能。代码如下:
  int ssize_t procread(struct file*file,char*buf,aize_t len,loff_t*offset); static ssize_t procwrite(struct file*file,char*buf,aize_t Ien,
  loff_t *offset);
  static struct file_operations procfop=
  {read:procread,
  write:procwrite,
  };
  static int init_routine(void)
  {struct proc_dir_entry *entry;
  entry=create_proc_entry("test",S_IRUSRIS_IwUSR,NULL);
  entry->proc_fops=&procfop;
  rutern;
  }
  
  4 /proc文件系统在RTAI中的应用
  
  RTAI是实时应用接口Real-Time Application Interface的缩写,提供了一个基于Linux的实时方案。RTAI利用Linux提 供的可加载内核模块机制来提供服务,完成实时功能。模块经过加载,成为内核的一部分,但是并没有被编译到内核里面去。它们被分别编译并连接成一组目标文件,这些文件能被插入到正在运行的内核,或从正在运行的内核中移走。RTAI提供的主要模块有RTAI主模块、RTAI调度器模块、RTAI命名管道fifo模块及RTAI共享内存模块等。
  
  4.1利用/proc文件系统用户获取实时内核的信息
  RTAI主模块是RTAI的核心模块,它是其他模块的基础。要加载其他模块,首先必须加载这个模块,没有它,任何实时任务都不能完成。当这个模块被加载后,在/proc目录下会自动生成一个rtai子目录,在其他模块如rtai_sched、rtai_fifos等模块加载后,rtai子目录下又有rtai、scheduler、fifos等文件。可以通过命令cat读取实时系统RTAI的有关信息,主要由…/rtai-x.x.x/arch/i386/rtai.c文件中的函数实现其功能:
  struct proc dir entry *rtai_proc_root=NULL;
  static int rtai_proc_register(void)
  {…
  rtai_proc_root=create_proc_entry(“rtai”,S_IFDIR,0);
  ent=create_proc_entry(“rtai”,S_IFREGIS_IRUGOIS_IwUSR,
  rtai_proc_root);
  ent->read proc=rtai_read_rtai;
  }
  
  4.2 利用/proc文件系统控制实时任务
  利用/proc文件系统write_proc函数可以修改内核数据,控制实时任务。首先使用create_proc_entry函数在/proc文件系统中创建一个虚拟文件,这个函数可以接收一个文件名、一组权限和这个文件在,proc文件系统中出现的位置。create_proc_entry的返回值是一个proc_dir_entry指针(或者为NULL,说明在create时发生了错误)。然后就可以使用这个返回的指针来配置这个虚拟文件的其他参数,例如在对该虚拟文件执行写操作时应该调用的write_proc函数。通过/proc文件的write_proc函数,修改内核中可以控制实时任务执行的变量,从而达到控制实时任务的目的。
  
  5 结束语
  
  Linux、RTAI都是开放源代码的,我们可以采取任何能想到的方法对它进行分析和改进,这是开放源代码提供给我们研究和学习的便利。但也应注意避免向内核中带入一些难以发现的错误。本文所提出的利用/proc文件实现实时系统监控和实时任务控制的方法,简单易行,用于开发应用程序非常方便。
  注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
其他文献
摘要:CMMI为软件产品及软件过程提供了一套定量的表示和分析,即软件度量的模型。有效的软件度量过程能促进组织的软件过程能力的改进。文章结合国内应用特点,介绍了基于CMMI的多层架构软件产品的度量模型,并着重讨论了基于CMMI的软件过程度量,总结了软件过程度量的工作方法和思路,提出了解决国内软件度量的一般性方法,为软件过程改进提供了可行的方法和实践。  关键词:CMMI;软件度量;软件过程能力;度量
期刊
摘要:伴随全球经济一体化进程的推进,信息技术在物流领域的应用和发展,传统的物流行业正逐步向电子物流转变。文章在分析物流企业业务流程的基础上,着重介绍了第三方物流信息系统的总体设计和关键技术,并提供了实现企业之间数据交换接口的具体实例。该系统能为企业带来竞争优势和经济效益,促进我国第三方物流的发展。  关键词:Web Service;物流信息系统;接口;数据交换    0 引言    全球的经济正朝
期刊
摘要:基于角色的访问控制,使角色成为信息访问主体,可以有效地解决安全访问问题。文章以OpenPERMIS为开发原型,采用Struts框架技术,设计并实现了RBAC中的属性证书管理系统,功能包括属性证书的创建、编辑、验证、撤销、查询等,为将RBAC系统成功运用到基于Web的应用奠定了基础。  关键词:Struts框架;属性证书管理;RBAC;访问控制    0 引言    基于角色的访问控制(Rol
期刊
摘要:为减少J2ME游戏运行平台的硬件环境对游戏的性能限制,在开发阶段必须对游戏的程序进行改良化设计和采用优化算法。文章从游戏运行性能的角度出发,分析了各种常用方案的不足,并给出了对象池技术、基本数据类型替换法、屏蔽函数计算三种能够节省资源开销和处理器时间以提高游戏运行性能的优化策略。实验对比表明,采用优化算法后性能得到了提高。  关键词:手机游戏;J2ME;MIDP;性能;优化    0 引言 
期刊
摘要:同一局域网内出现多种不同的Windows系统,安装不同版本Windows操作系统的计算机之间不能互访。文章从网络协议、计划任务等多方面探讨了WindowsXP操作系统不能与其它Windows操作系统互访的原因,并在此基础上提出了相应的解决方法。  关键词:WinXP;网络协议;注册表;计划任务    0 引言    现在,已经有许多人在使用Win2000和WinXP来联网。因为各机器使用的操
期刊
摘要:针对Web数据打印缺乏灵活性的问题,使用中间件动态生成的XML,结合XSL如Document对象,提出了几种用户可自定义打印格式的通用解决方案。该方案应用于“国有资产智能管理系统”项目取得了良好的效果。  关键词:中间件;XML;XSL;Document;数据打印;Web    0 引言    随着数据库技术与网络的发展以及互联网的普及,基于B/S(Browser/Server)模式的软件应
期刊
摘要:针对DOS程序用户界面差、不易掌握的缺点,提出了应用模拟键盘技术,并结合进程检测技术进行数据传递的方法。该方法不需要对原DOS程序进行任何修改,就能将DOS程序升级成图形操作界面。同时该方法还能对DOS程序的运行过程状态进行监测,为Windows下DOS应用程序的改造和利用提供了一种简便易行的途径。  关键词:DOS程序;升级;GUI;模拟键盘;CPU占用率    0 引言    在DOS时
期刊
摘要:首先介绍了嵌入式Linux环境下设备驱动程序的开发流程,详细描述了Linux设备驱动程序的体系结构和Linux设备文件的概念。然后通过一个例子描述了如何设计和编写Linux设备驱动程序,并解释了其中的核心代码。最后构建一个Glade工程来调用这个设备驱动程序,完成测试工作。  关键词:嵌入式Linux;设备文件;设备驱动;Glade    0 引言    Linux是开放源代码的操作系统,由
期刊
摘要:程序员在设计应用程序时,通常把程序划分为若干功能较为单一的模块,然后分别予以实现,最后再把所有的模块装配起来。这种程序设计中分而治之的策略,被称为模块化程序设计。C语言中,函数是程序的基本组成单位,也是模块化程序设计的惟一工具,使用函数调用和嵌套,可使程序设计变得简单直观、易读和易维护,并可大大地减轻程序员的代码工作量。文章就C/C++语言在程序设计中的解决方法、特点进行阐述。  关键词:模
期刊
摘 要:RFID是一项蓬勃发展的技术,拥有广阔的发展前景和巨大的市场潜力。文章通過对RFID技术的组成、原理、应用及发展瓶颈等方面的分析,让人们了解RPID技术,从而能更好地发展和应用该技术。  关键词:RFID技术;电子标签;阅读器;天线
期刊