Linux Device Driver Learning notes--proc (supplemental seq_file) of kernel debugging methods __linux

Source: Internet
Author: User

The proc implementation in the previous section is relatively straightforward for switch files, control files, and files that display very little information, but it is awkward to output large amounts of information like meminfo, or structured information like Cpuinfo, and the code is poorly understood and maintained. The kernel provides another solution to simplify the implementation of this proc file----Seq_file interface.

The Set_file interface assumes that you are creating a virtual file that involves a series of items that must be returned to the user space. To use Seq_file, you have to create a simple "iterator" object that can create a position (start) in a sequence, move forward (next), and output a sequence of items (show). It may sound complicated, but the process is actually very simple.

The Seq_file interface can realize the previous unstructured information display, also can realize the structured information display, and both implementations of the code are relatively simple and clear. Use the Seq_file interface to include header files <linux/seq_file.h>.

Seq_file use comparison specification, and other file operation steps are more consistent, so it seems easier, we can analyze the kernel of meminfo and cpuinfo to learn the unstructured and structured information display implementation steps. 1, Structured information display method The first step: Call Proc_create to create the corresponding proc file when the module is initialized

static int __init proc_cpuinfo_init (void)
{
	proc_create ("Cpuinfo", 0, NULL, &proc_cpuinfo_operations);
	return 0;
}

Step Two: When the module unload, call the Remove_proc_entry function to delete the corresponding proc file, of course because cpuinfo implementation in the kernel code, does not involve unloading, so cpuinfo did not delete the corresponding proc file operation, But the kernel modules we write ourselves involve this scenario, so we need to implement this step.


Step Three: Define the file_operations structure (used when created in the first step)

static const struct File_operations proc_cpuinfo_operations = {
	. Open		= Cpuinfo_open,
	. Read		= Seq_read ,
	. Llseek		= Seq_lseek,
	. Release	= Seq_release,
};

The fourth step is to implement the File_operations open function, and in the open function, we recommend that the proc file be contacted with the seq_file mechanism's four iterators. And read, Llseek, release and so are all seq_file to achieve a good framework, do not need to implement additional.

extern const struct Seq_operations cpuinfo_op;
static int Cpuinfo_open (struct inode *inode, struct file *file)
{return
	seq_open (file, &cpuinfo_op);
}

step Fifth, define the seq_operations structure body

const struct Seq_operations cpuinfo_op = {
	. Start	= C_start,
	. Next	= C_next,
	. Stop	= C_stop,
	. Show	= Show_cpuinfo,
};

The sixth step, implement the iterator (Start/next/stop/show), according to their own needs to achieve, here is only cpuinfo implementation

Start iterator:

static void *c_start (struct seq_file *m, loff_t *pos)
{
	*pos = Cpumask_next (*pos-1, cpu_online_mask);
	if ((*pos) < Nr_cpu_ids) return
		&cpu_data (*pos);
	return NULL;
}


Next iterator:

static void *c_next (struct seq_file *m, void *v, loff_t *pos)
{
	(*pos) + +;
	Return C_start (M, POS);
}

Stop iterator, generally implemented as null

static void C_stop (struct seq_file *m, void *v)
{
}

Show iterator, the most important information displayed

static int show_cpuinfo (struct seq_file *m, void *v) {struct cpuinfo_x86 *c = v;
	unsigned int cpu;

	int i;
	CPU = c->cpu_index; seq_printf (M, "processor\t:%u\n" "Vendor_id\t:%s\n" "CPU family\t:%d\n" "model\t\t:%u\n" "Model NA Me\t:%s\n ", CPU, c->x86_vendor_id[0]? C-&GT;X86_VENDOR_ID: "Unknown", C->x86, C->x86_model, c->x86_model_id[0]?

	C-&GT;X86_MODEL_ID: "Unknown");
	if (C->x86_mask | | c->cpuid_level >= 0) seq_printf (M, "stepping\t:%d\n", c->x86_mask);
	Else seq_printf (M, "stepping\t:unknown\n");

	if (C->microcode) seq_printf (M, "microcode\t:0x%x\n", C->microcode);

		if (Cpu_has (c, X86_FEATURE_TSC)) {unsigned int freq = Cpufreq_quick_get (CPU);
		if (!freq) freq = cpu_khz; seq_printf (M, "CPU mhz\t\t:%u.%0
	3u\n ", freq/1000, (freq% 1000));

	}/* Cache size */if (c->x86_cache_size >= 0) seq_printf (M, "cache size\t:%d kb\n", c->x86_cache_size); Show_cpuiNfo_core (M, c, CPU);

	Show_cpuinfo_misc (M, c);
	seq_printf (M, "flags\t\t:"); for (i = 0; i < 32*ncapints i++) if (Cpu_has (c, i) && x86_cap_flags[i]!= NULL) seq_printf (M, "%s", x86_

	Cap_flags[i]); seq_printf (M, "\nbogomips\t:%lu.%0

2lu\n ", c->loops_per_jiffy/(500000/hz), (c->loops_per_jiffy/(5000/hz))% 100);
#ifdef config_x86_64 if (c->x86_tlbsize > 0) seq_printf (M, "TLB size\t:%d 4K pages\n", c->x86_tlbsize);
	#endif seq_printf (M, "Clflush size\t:%u\n", c->x86_clflush_size);
	seq_printf (M, "cache_alignment\t:%d\n", c->x86_cache_alignment);

	seq_printf (M, "address sizes\t:%u bits physical,%u bits virtual\n", c->x86_phys_bits, c->x86_virt_bits);
	seq_printf (M, "Power Management:"); for (i = 0; i < i++) {if (C->x86_power & (1 << i)) {if (I < array_size (x86_power_flags) ;& X86_power_flags[i]) seq_printf (M, "%s%s", x86_power_flags[i][0]? "": "", x86_power_flags[i]);
		Else seq_printf (M, "[%d]", i);

	} seq_printf (M, "\ n \");
return 0; }

2, unstructured information display mode Step One: Call Proc_create when the module is initialized to create the corresponding proc file

static int __init proc_meminfo_init (void)
{
	proc_create ("Meminfo", 0, NULL, &meminfo_proc_fops);
	return 0;
}

Step Two: When the module unload, call the Remove_proc_entry function to delete the corresponding proc file, of course because meminfo implementation in the kernel code, does not involve unloading, so meminfo did not delete the corresponding proc file operation, But the kernel modules we write ourselves involve this scenario, so we need to implement this step.

Step Three: Define the file_operations structure (used when created in the first step)

static const struct File_operations meminfo_proc_fops = {
	. Open		= Meminfo_proc_open,
	. Read		= Seq_ Read,
	. Llseek		= Seq_lseek,
	. Release	= Single_release,
};

The fourth step, the implementation of the File_operations open function, because the Meminfo unstructured information display, so we do not need to implement start/next/stop, such as iterators, only to implement show to display information, So you don't need to define a seq_operations structure like cpuinfo and call Seq_open to establish the connection between proc file and Seq_file iterator. The Seq_file interface provides a single_open interface for unstructured information display, so call Single_open in open.

static int Meminfo_proc_open (struct inode *inode, struct file *file)
{return
	single_open (file, meminfo_proc_ Show, NULL);

The fifth step, just to implement show iterator Meminfo_proc_show can

static int meminfo_proc_show (struct seq_file *m, void *v) {struct I;
	unsigned long committed;
	unsigned long allowed;
	struct Vmalloc_info VMI;
	Long cached;
	unsigned long pages[nr_lru_lists];

int LRU;
 * * Display in kilobytes.
	* * #define K (x) ((x) << (page_shift-10)) Si_meminfo (&i);
	Si_swapinfo (&i);
	Committed = Percpu_counter_read_positive (&vm_committed_as);

	Allowed = ((Totalram_pages-hugetlb_total_pages ()) * sysctl_overcommit_ratio/100) + total_swap_pages;
	cached = Global_page_state (nr_file_pages)-Total_swapcache_pages-i.bufferram;

	if (cached < 0) cached = 0;

	Get_vmalloc_info (&AMP;VMI);

	for (LRU = lru_base; LRU < nr_lru_lists; lru++) Pages[lru] = global_page_state (nr_lru_base + LRU);
	 /* Tagged format, for easy grepping and expansion.         */seq_printf (M, "Memtotal:%8lu kb\n" "Memfree:%8lu kb\n" "Buffers:%8lu kb\n" "Cached: %8lu kb\n "" Swapcached:%8lu kb\n "" Active:%8lu kb\n "" Inactive:%8lu kb\n "" Active (anon):%8lu kb\n "" Inactive (anon):%8lu kb\n "" Active (file):%8lu kb\n "" Inactive (file):%8lu kb\n "" Unevictable:%8lu kb\n "" Mlocked:%8lu kb\n "#ifdef CONF Ig_highmem "Hightotal:%8lu kb\n" "Highfree:%8lu kb\n" "Lowtotal:%8lu kb\n" "Lowfree:%8 Lu kb\n "#endif #ifndef Config_mmu" mmapcopy:%8lu kb\n "#endif" Swaptotal:%8lu kb\n "" Swapfree:% 8lu kb\n "" Dirty:%8lu kb\n "" Writeback:%8lu kb\n "" Anonpages:%8lu kb\n "" Mapped:%8l U kb\n "" Shmem:%8lu kb\n "slab:%8lu kb\n" "Sreclaimable:%8lu kb\n" "Sunreclaim:%8lu Kb\n "" Kernelstack:%8lu kb\n "" Pagetables:%8lu kb\n "#ifdef config_quicklist" quicklists:%8lu kb\n "#e Ndif "nfs_unstable:%8lu kb\n" "Bounce:%8lu kb\n" "Writebacktmp:%8lu kb\n" "Commitlimit:%8lu kb\ N "" Committed_as:%8Lu kb\n "" Vmalloctotal:%8lu kb\n "vmallocused:%8lu kb\n" "Vmallocchunk:%8lu kb\n" #ifdef CONFIG_MEMORY_FA Ilure "hardwarecorrupted:%5lu kb\n" #endif, K (I.totalram), K (I.freeram), K (I.bufferram), K (cached), K (Tota L_swapcache_pages), K (Pages[lru_active_anon] + pages[lru_active_file]), K (Pages[lru_inactive_anon) + Pages[LRU_INACT Ive_file]), K (Pages[lru_active_anon]), K (Pages[lru_inactive_anon]), K (Pages[lru_active_file), K (Pages[lru_inactiv E_file]), K (pages[lru_unevictable]), K (Global_page_state (Nr_mlock)), #ifdef Config_highmem K (I.totalhigh), K (i.fre Ehigh), K (I.totalram-i.totalhigh), K (I.freeram-i.freehigh), #endif #ifndef Config_mmu K ((unsigned long) atomic_long_ Read (&mmap_pages_allocated)), #endif K (I.totalswap), K (I.freeswap), K (Global_page_state (Nr_file_dirty)), K (Glo Bal_page_state (Nr_writeback)), K (Global_page_state (Nr_anon_pages)), K (Global_page_state (nr_file_mapped)), K (
		Global_page_state (NR_SHMEM)),K (Global_page_state (nr_slab_reclaimable) + global_page_state (nr_slab_unreclaimable)), K (global_page_state _reclaimable)), K (Global_page_state (nr_slab_unreclaimable)), Global_page_state (nr_kernel_stack) * thread_size/1024 , K (Global_page_state (nr_pagetable)), #ifdef config_quicklist K (Quicklist_total_size ()), #endif K global_page_state ( Nr_unstable_nfs)), K (Global_page_state (Nr_bounce)), K (Global_page_state (Nr_writeback_temp)), K (allowed), K (Committ ed), (unsigned long) vmalloc_total >> vmi.used >> #ifdef vmi.largest_chunk >> config_mem

	Ory_failure, Atomic_long_read (&mce_bad_pages) << (page_shift-10) #endif);

	Hugetlb_report_meminfo (m);

	Arch_report_meminfo (m);
return 0; #undef K}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.