seq_file机制

在老版本的Linux内核中,proc文件系统有一个缺陷:如果输出内容大于1个内存页,需要多次读,因此处理起来很难。另外,如果输出内容太大,速度会比较慢。在2.6内核中,由于大量使用了seq_file功能,使得内核输出大文件信息更容易。使用seq_file需要包含头文件linux/seq_file.h,并定义一个seq_operations结构:

 
 
  1. struct seq_operations {  
  2.         void * (*start) (struct seq_file *m, loff_t *pos);// 指定seq_file文件的读开始位置  
  3.         void (*stop) (struct seq_file *m, void *v);//关闭seq_file  
  4.         // 把seq_file文件的当前读位置移动到下一个读位置  
  5.         void * (*next) (struct seq_file *m, void *v, loff_t *pos);  
  6.         int (*show) (struct seq_file *m, void *v);//格式化输出  
  7. };  

seq_file的常用操作接口如下:
 
 
  1. int seq_open(struct file *, const struct seq_operations *);//打开  
  2. ssize_t seq_read(struct file *, char __user *, size_t, loff_t *);//读  
  3. loff_t seq_lseek(struct file *, loff_t, int);//定位  
  4. int seq_release(struct inode *, struct file *);//释放  
  5. int seq_escape(struct seq_file *, const char *, const char *);//写缓冲,忽略某些字符  
  6. int seq_putc(struct seq_file *m, char c);// 把一个字符输出到seq_file文件  
  7. int seq_puts(struct seq_file *m, const char *s);// 把一个字符串输出到seq_file文件  

下面以cpuinfo为例说明seq_file在proc中的使用。
 
 
  1. void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)  
  2. {  
  3.     struct proc_dir_entry *entry;  
  4.     entry = create_proc_entry(name, mode, NULL);  
  5.     if (entry)  
  6.         entry->proc_fops = f;  
  7. }  
  8. void __init proc_misc_init(void)  
  9. {  
  10.     …  
  11.     create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); //创建/proc目录  
  12. }  

定义proc_cpuinfo_operations:
 
 
  1. static const struct file_operations proc_cpuinfo_operations = {  
  2.     .open   = cpuinfo_open,  
  3.     .read       = seq_read,  
  4.     .llseek = seq_lseek,  
  5.     .release    = seq_release,  
  6. };  

接下来看cpuinfo_open:
 
 
  1. static int cpuinfo_open(struct inode *inode, struct file *file)  
  2. {  
  3.     return seq_open(file, &cpuinfo_op);  
  4. }  

cpuinfo_op是与硬件平台相关的。ARM的cpuinfo_op在/arc/arm/kernel/setup.c中:
 
 
  1. struct seq_operations cpuinfo_op = {  
  2.     .start  = c_start,  
  3.     .next   = c_next,  
  4.     .stop   = c_stop,  
  5.     .showc_show 
  6. };  

cpuinfo_op就是实际上对/proc/ cpuinfo进行修改的操作接口,其中最重要的是c_show:

 
 
  1. static int c_show(struct seq_file *m, void *v)  
  2. {  
  3.     int i;  
  4.     seq_printf(m, "Processor\t: %s rev %d (%s)\n",  
  5.            cpu_name, (int)processor_id & 15, elf_platform);  
  6. #if defined(CONFIG_SMP)//针对多处理器  
  7.     for_each_online_cpu(i) {  
  8.         seq_printf(m, "processor\t: %d\n", i);  
  9.         seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",  
  10.                per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),  
  11.                (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);  
  12.     }  
  13. #else /* CONFIG_SMP */  
  14.     seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",  
  15.            loops_per_jiffy / (500000/HZ),  
  16.            (loops_per_jiffy / (5000/HZ)) % 100);  
  17. #endif  
  18.     seq_puts(m, "Features\t: ");  
  19.     for (i = 0; hwcap_str[i]; i++)  
  20.         if (elf_hwcap & (1 << i))  
  21.             seq_printf(m, "%s ", hwcap_str[i]);  
  22.     seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);  
  23.     seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);  
  24.     if ((processor_id & 0x0008f000) == 0x00000000) {/* pre-ARM7 */  
  25.         seq_printf(m, "CPU part\t: %07x\n", processor_id >> 4);  
  26.     } else {  
  27.         if ((processor_id & 0x0008f000) == 0x00007000) {/* ARM7 */  
  28.             seq_printf(m, "CPU variant\t: 0x%02x\n",  
  29.                    (processor_id >> 16) & 127);  
  30.         } else {/* ARM7以上的CPU */  
  31.             seq_printf(m, "CPU variant\t: 0x%x\n",  
  32.                    (processor_id >> 20) & 15);  
  33.         }  
  34.         seq_printf(m, "CPU part\t: 0x%03x\n",(processor_id >> 4) & 0xfff);  
  35.     }  
  36.     seq_printf(m, "CPU revision\t: %d\n", processor_id & 15);  
  37.     {  
  38.         unsigned int cache_info = read_cpuid(CPUID_CACHETYPE);  
  39.         if (cache_info != processor_id) {  
  40.             seq_printf(m, "Cache type\t: %s\n"  
  41.                       "Cache clean\t: %s\n"  
  42.                       "Cache lockdown\t: %s\n"  
  43.                       "Cache format\t: %s\n",  
  44.                    cache_types[CACHE_TYPE(cache_info)],  
  45.                    cache_clean[CACHE_TYPE(cache_info)],  
  46.                    cache_lockdown[CACHE_TYPE(cache_info)],  
  47.                    CACHE_S(cache_info) ? "Harvard" : "Unified");  
  48.             if (CACHE_S(cache_info)) {  
  49.                 c_show_cache(m, "I", CACHE_ISIZE(cache_info));  
  50.                 c_show_cache(m, "D", CACHE_DSIZE(cache_info));  
  51.             } else {  
  52.                 c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));  
  53.             }  
  54.         }  
  55.     }  
  56.     seq_puts(m, "\n");  
  57.     seq_printf(m, "Hardware\t: %s\n", machine_name);  
  58.     seq_printf(m, "Revision\t: %04x\n", system_rev);  
  59.     seq_printf(m, "Serial\t\t: %08x%08x\n",system_serial_high, system_serial_low);  
  60.     return 0;  
  61. }  
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值