mini2440之/proc 目录中的文件创建及测试

在玩mini2440的时候,发现自己要经常查看/proc目中的某些文件,如:modules,mtd,iomem等.其中每个目录和文件都是动态创建的.并不存在于磁盘上

[@mini2440 /proc]#ls
1             302           cmdline       iomem         mounts        tty
11            306           cpu           ioports       mtd           uptime
2             4             cpuinfo       irq           net           version
209           416           crypto        kallsyms      pagetypeinfo  vmallocinfo
211           5             devices       kmsg          partitions    vmstat
213           628           diskstats     kpagecount    self          yaffs
222           666           driver        kpageflags    slabinfo      zoneinfo
228           669           execdomains   loadavg       softirqs
244           671           fb            locks         stat
251           asound        filesystems   meminfo       sys
298           buddyinfo     fs            misc          sysvipc
3             bus           interrupts    modules       timer_list

上面为proc目录中的文件及文件夹,上面的文件及目录是怎么来的了?

在我们制作的根文件系统中,在文件/etc/fstab中又如下内容:

[@mini2440 /etc]#cat fstab
#device mount-point type option dump fsck order
proc /proc proc defaults 0 0
proc /testProcDirectory proc defaults 0 0
  这个条是自己加的,来测试在目录/testProcDirectory中和/proc中的内容相同

sysfs /sys sysfs defaults 0 0
mdev /dev ramfs defaults 0 0
none /var ramfs defaults 0 0
none /tmp ramfs defaults 0 0

proc文件系统相当于内核的一个快照,该目录下的所有信息都是动态的从正在运行的内核中读取。

基于这种原因,/proc文件系统就成为了用户和内核之间交互的接口。

一方面,用户可以从/proc文件系统中读取很多内核释放出来的信息;另一方面,内核也可以在恰当的时候从用户那里得到输入信息,从而改变内核的相关状态和配置。

相比传统的文件系统,/proc是一种特殊的文件系统,即虚拟文件系统。这里的虚拟是强调/proc文件系统下的所有文件都存在于内存中而不是磁盘上。也就是说/proc文件系统只占用内存空间,而不占用系统的外存空间。

 

现在我们在linux内核中找个相关的代码来看看,究竟/proc目录中的文件时如何建立起来的?

#include <linux/fs.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

static int devinfo_show(struct seq_file *f, void *v)
{
	int i = *(loff_t *) v;

	if (i < CHRDEV_MAJOR_HASH_SIZE) {
		if (i == 0)
			seq_printf(f, "Character devices:\n");
		chrdev_show(f, i);
	}
#ifdef CONFIG_BLOCK
	else {
		i -= CHRDEV_MAJOR_HASH_SIZE;
		if (i == 0)
			seq_printf(f, "\nBlock devices:\n");
		blkdev_show(f, i);
	}
#endif
	return 0;
}

static void *devinfo_start(struct seq_file *f, loff_t *pos)
{
	if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
		return pos;
	return NULL;
}

static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
{
	(*pos)++;
	if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE))
		return NULL;
	return pos;
}

static void devinfo_stop(struct seq_file *f, void *v)
{
	/* Nothing to do */
}

static const struct seq_operations devinfo_ops = {
	.start = devinfo_start,
	.next  = devinfo_next,
	.stop  = devinfo_stop,
	.show  = devinfo_show
};

static int devinfo_open(struct inode *inode, struct file *filp)
{
	return seq_open(filp, &devinfo_ops);
}

static const struct file_operations proc_devinfo_operations = {
	.open		= devinfo_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

static int __init proc_devices_init(void)
{
	proc_create("devices", 0, NULL, &proc_devinfo_operations);
	return 0;
}
module_init(proc_devices_init);

在看上面的代码之前,现看看/proc/devices 文件中的内容:

[@mini2440 /proc]#cat devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 14 sound
 21 sg
 29 fb
 81 video4linux
 89 i2c
 90 mtd
116 alsa
128 ptm
136 pts
400 leds
149 leds_01
180 usb
188 ttyUSB
189 usb_device
195 led1_dev_01
204 s3c2410_serial
254 rtc

Block devices:
259 blkext
  7 loop
  8 sd
 31 mtdblock
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc

上面的devices文件中有俩个标示符:Character devicesBlock devices。

 现在来看看上面的代码中的devinfo_show()函数中有上面所说的描述符。从上面的代码中,我们不难猜/proc目录中文件的创建方法。

 下面自己写个测试程序,看看proc目录中的文件是如何创建的。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>	/* printk() */
#include <linux/slab.h>		/* kmalloc() */
#include <linux/fs.h>		/* everything... */
#include <linux/errno.h>	/* error codes */
#include <linux/types.h>	/* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>	/* O_ACCMODE */
#include <linux/seq_file.h>
#include <asm/system.h>		/* cli(), *_flags */
#include <asm/uaccess.h>	/* copy_*_user */

#define LEN 100
static char dataBuf[LEN];
static char *testString ="suiyuan19840208";

static ssize_t proc_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
        int size =strlen(dataBuf);
	if(size == 0)
	{
	 strcpy(dataBuf,testString);
	}
	  if(copy_to_user(buf, dataBuf, strlen(dataBuf)))
	   {
	     return -EFAULT; 
	     printk("copy_to_user error \n");
	   }
       printk("proc_read: buf:%s\n",buf);
	   return 0;
}
static int proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
	int len;
	if (count > LEN)
	{
	 len = LEN;
	}
	else
	{
	 len = count;
	}
	if (copy_from_user(dataBuf, buffer, len))
	{
	   return -EFAULT;
	}
      dataBuf[len-1]='\0';
      printk("proc_write: len:%d \tdataBuf:%s\n",len,dataBuf);
      return len;
}
static int proc_open(struct inode *inode, struct file *file)
{
    printk("proc_open:default string:%s\n",testString);
    return 0;

}

static const struct file_operations cmdline_proc_fops = {
	.open		= proc_open,
	.read		= proc_read,
	.write          = proc_write,
	.llseek		= seq_lseek,	//注意:函数没有自己定义 
	.release	= single_release,           //注意:函数没有自己定义,测试时候需要将其注释
 };

static int __init proc_cmdline_init(void)
{
	proc_create("test_String", 0, NULL, &cmdline_proc_fops);
	return 0;
}
module_init(proc_cmdline_init);
 

将上面的代码添加到自己的可以编译的内核路径中,进行编译。

  CHK     include/linux/compile.h
  CC      drivers/suiyuan/testProc.o 我自己添加的路径为drivers/suiyuan/目录中
drivers/suiyuan/testProc.c:63: warning: initialization from incompatible pointer type
加载内核。

可以在目录/proc目录中看到以下:

[@mini2440 /proc]#ls
1             302           cmdline       iomem         mounts        timer_list
11            306           cpu           ioports       mtd           tty
2             4             cpuinfo       irq           net           uptime
209           416           crypto        kallsyms      pagetypeinfo  version
211           5             devices       kmsg          partitions    vmallocinfo
213           628           diskstats     kpagecount    self          vmstat
222           666           driver        kpageflags    slabinfo      yaffs
228           668           execdomains   loadavg       softirqs      zoneinfo
244           672           fb            locks         stat
251           asound        filesystems   meminfo       sys
298           buddyinfo     fs            misc          sysvipc
3             bus           interrupts    modules       test_String 此文件就是上面代码所生成的目录

然而当对文件 test_string 进行读取的时候,出现如下错误:

[@mini2440 /proc]#cat test_String
proc_open:default string:suiyuan19840208
proc_read: buf:suiyuan19840208
Unable to handle kernel NULL pointer dereference at virtual address 00000034
pgd = c39b0000
[00000034] *pgd=339b4031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#2]
last sysfs file: /sys/devices/platform/soc-audio/sound/card0/mixer/dev
Modules linked in:
CPU: 0    Tainted: G      D     (2.6.32.2-FriendlyARM #40)
PC is at single_release+0x10/0x2c
LR is at proc_reg_release+0xbc/0x13c

pc : [<c00b3488>]    lr : [<c00d38b4>]    psr: a0000013
sp : c39b7ef8  ip : c39b7f10  fp : c39b7f0c
r10: 00000000  r9 : c39b6000  r8 : c39b5700
r7 : c00b3478  r6 : c392c600  r5 : c348cdf8  r4 : c3950600
r3 : 00000000  r2 : c3950600  r1 : c39b5700  r0 : c348cdf8
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 339b0000  DAC: 00000015
Process cat (pid: 673, stack limit = 0xc39b6270)
Stack: (0xc39b7ef8 to 0xc39b8000)
7ee0:                                                       c3950600 c348cdf8
7f00: c39b7f34 c39b7f10 c00d38b4 c00b3488 c39b5700 c3934700 c348be00 c348cdf8
7f20: c0030088 c39b6000 c39b7f5c c39b7f38 c009c328 c00d3808 c39b5700 00000000
7f40: c39356c0 00000006 c0030088 c39b6000 c39b7f6c c39b7f60 c009c468 c009c2d4
7f60: c39b7f8c c39b7f70 c0099030 c009c444 0000000f 00000000 00000003 00000006
7f80: c39b7fa4 c39b7f90 c00990e8 c0098fe8 bedd8e68 00000000 00000000 c39b7fa8
7fa0: c002fee0 c0099060 bedd8e68 00000000 00000003 00000000 00001000 001e9e38
7fc0: bedd8e68 00000000 00000003 00000006 0000008f 00000000 00000000 00000000
7fe0: 00000000 bedd8cb0 0008c5c8 00008dbc 60000010 00000003 30539031 30539431
Backtrace:
[<c00b3478>] (single_release+0x0/0x2c) from [<c00d38b4>] (proc_reg_release+0xbc/0x13c)
 r5:c348cdf8 r4:c3950600
[<c00d37f8>] (proc_reg_release+0x0/0x13c) from [<c009c328>] (__fput+0x64/0x170)
 r9:c39b6000 r8:c0030088 r7:c348cdf8 r6:c348be00 r5:c3934700
r4:c39b5700
[<c009c2c4>] (__fput+0x0/0x170) from [<c009c468>] (fput+0x34/0x38)
 r9:c39b6000 r8:c0030088 r7:00000006 r6:c39356c0 r5:00000000
r4:c39b5700
[<c009c434>] (fput+0x0/0x38) from [<c0099030>] (filp_close+0x58/0x78)
[<c0098fd8>] (filp_close+0x0/0x78) from [<c00990e8>] (sys_close+0x98/0xc4)
 r7:00000006 r6:00000003 r5:00000000 r4:0000000f
[<c0099050>] (sys_close+0x0/0xc4) from [<c002fee0>] (ret_fast_syscall+0x0/0x28)
 r5:00000000 r4:bedd8e68
Code: e1a0c00d e92dd830 e24cb004 e5913068 (e5934034)
---[ end trace 392f42bfaac48aec ]---
Segmentation fault

对上面的错误,到网上找了找,LDD 书上面有提到类似的信息。

最后自己看了看,自己没有实现,.llseek = seq_lseek和release = single_release,这俩个函数,在上面的提示中能得到帮助。故在读取时候,出现了如上的错误。

正确代码的测试结构如下:

[@mini2440 /proc]#cat test_String 
proc_open:default string:suiyuan19840208
proc_read: buf:suiyuan19840208
[@mini2440 /proc]#echo "suiyuan_testing" > test_String 
proc_open:default string:suiyuan19840208
proc_write: len:16      dataBuf:suiyuan_testing
[@mini2440 /proc]#cat test_String 
proc_open:default string:suiyuan19840208
proc_read: buf:suiyuan_testing

 

在proc_create()函数中,涉及到如下的数据结构。

struct proc_dir_entry {
	unsigned int low_ino;
	unsigned short namelen;
	const char *name;
	mode_t mode;
	nlink_t nlink;
	uid_t uid;
	gid_t gid;
	loff_t size;
	const struct inode_operations *proc_iops;
	/*
	 * NULL ->proc_fops means "PDE is going away RSN" or
	 * "PDE is just created". In either case, e.g. ->read_proc won't be
	 * called because it's too late or too early, respectively.
	 *
	 * If you're allocating ->proc_fops dynamically, save a pointer
	 * somewhere.
	 */
	const struct file_operations *proc_fops;
	struct proc_dir_entry *next, *parent, *subdir;
	void *data;
	read_proc_t *read_proc;
	write_proc_t *write_proc;
	atomic_t count;		/* use count */
	int pde_users;	/* number of callers into module in progress */
	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
	struct completion *pde_unload_completion;
	struct list_head pde_openers;	/* who did ->open, but not ->release */
};


 

 

你可能感兴趣的:(c,String,struct,File,character,filesystems)