Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use proc of Linux

2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the knowledge of "how to use the proc of Linux". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

1. Introduction

Using printk in the kernel, you can save the debugging information in the log_buf buffer. You can use the command # cat / proc/kmsg to print out the data of the number area of the buffer and write the kmsg file yourself. We call it mymsg.

2. Check how / proc/kmsg is written in the kernel!

In the Proc_misc.c (fs\ proc) file:

Void _ init proc_misc_init (void) {. Struct proc_dir_entry * entry; / / A proc entry is created here kmsg entry = create_proc_entry ("kmsg", S_IRUSR, & proc_root); if (entry) / * construct a proc_fops structure * / entry- > proc_fops = & proc_kmsg_operations;. }

In the Kmsg.c (fs\ proc) file:

Const struct file_operations proc_kmsg_operations = {.read = kmsg_read, .poll = kmsg_poll, .open = kmsg_open, .release = kmsg_release,}

When cat / proc/kmsg is used in user space, kmsg_open is called. When the kmsg_read function is called, the data in log_buf is read and copied to user space for display.

3. Before we write, we need to learn about the circular queue

Ring queue is a very useful data structure in practical programming. It has the following characteristics:

It is an end-to-end FIFO data structure, using array linear space, data organization is simple, can quickly know whether the queue is empty. Can access data at a very fast speed.

For reasons of simplicity and efficiency, ring queues are implemented even in hardware.

Ring queues are widely used in network data sending and receiving. Ring queues are used in data exchange between different programs (for example, the kernel exchanges a large amount of data with applications and receives large amounts of data from hardware).

3.1. Principle of ring queue implementation

There is no ring structure in memory, so the ring queue is actually the linear space of the array. How do you deal with the data when it gets to the tail? It will go back to the 0 position to process. The reversal of this is performed through a modular operation.

Therefore, the ring queue logically connects the array element Q [0] with Q [MAXN-1] to form a ring space where the queue is stored.

To facilitate reading and writing, an array subscript is also used to indicate the read and write location of the queue. Head/tail. Where head points to a location that can be read, and tail points to a location that can be written.

The key to a circular queue is to determine whether the queue is empty or full. When tail catches up with head, the queue is full, when head catches up with tail, the queue is empty. But how to know who catches up with whom. Some auxiliary means are needed to judge.

There are two ways to judge whether the ring queue is empty or full.

(1) append a flag bit tag

When head catches up with tail and the queue is empty, it makes tag=0

When tail catches up with head and the queue is full, it makes tag=1

(2) restrict tail to catch up with head, that is, there is at least one element space between the end node and the head node of the team.

Queue empty: head==tail

Queue full: (tail+1)% MAXN = = head

4. Programming

# include # define MYLOG_BUF_LEN 1024 static char mylog_ buf [MYLOG _ BUF_LEN]; static char tmp_ buf [MYLOG _ BUF_LEN]; static int mylog_r = 0; static int mylog_w = 0; static int mylog_r_tmp = 0; / * hibernation queue initialization * / static DECLARE_WAIT_QUEUE_HEAD (mymsg_waitq) / * * determine whether the ring queue is empty * return 0: not empty; return 1: indicate empty * / static int is_mylog_empty (void) {return (mylog_r = = mylog_w) } / * * determine whether the ring queue is full * return 0: indicate dissatisfaction; return 1: indicate full * / static int is_mylog_full (void) {return ((mylog_w + 1)% MYLOG_BUF_LEN = = mylog_r) } / * * when reading, determine whether the data in the ring queue is empty * return 0: not empty return 1: indicate empty * / static int is_mylog_empty_for_read (void) {return (mylog_r_tmp = = mylog_w) Input: C character unit: 1byte * output: none * / static void mylog_putc (char c) {if (is_mylog_full ()) {/ * if the queue is detected to be full, discard the data * / mylog_r= (mylog_r + 1)% MYLOG_BUF_LEN / * mylog_r_tmp cannot be greater than mylog_r*/ if ((mylog_r_tmp + 1)% MYLOG_BUF_LEN = = mylog_r) mylog_r_tmp= mylog_r;} mylog_ buf [mylog _ w] = c / * when mylog_w=1023 (mylog_w+1)% MYLOG_BUF_LEN = 0, return to the queue header and loop * / mylog_w= (mylog_w+1)% MYLOG_BUF_LEN; / * Wake up the process waiting for data * / wake_up_interruptible (& mymsg_waitq) } / * * read characters from the circular queue * input: * p unit: 1byte * output: 1 indicates success * / static int mylog_getc (char * p) {/ * determine whether the data is empty * / if (is_mylog_empty_for_read ()) {return 0;} * p = mylog_ buf [mylog _ r_tmp] Mylog_r_tmp = (mylog_r_tmp + 1)% MYLOG_BUF_LEN; return 1;} / * * call myprintk with the same usage as printf * / int myprintk (const char * fmt,...) {va_list args; int i; int j; va_start (args, fmt); I = vsnprintf (tmp_buf, INT_MAX, fmt, args); va_end (args); for (j = 0; j

< i; j++) mylog_putc(tmp_buf[j]); return i; } static ssize_t mymsg_read(struct file *file, char __user *buf, size_t count, loff_t*ppos) { int error=0; size_t i=0; char c; /* 把mylog_buf的数据copy_to_user, return*/ /*非阻塞 和 缓冲区为空的时候返回*/ if ((file->

F_flags & O_NONBLOCK) & & is_mylog_empty () return-EAGAIN; / * hibernation queue wait_event_interruptible (xxx,0)-> hibernation * / error= wait_event_interruptible (mymsg_waitq,! is_mylog_empty_for_read ()); / * copy_to_user*/ while (! error & & (mylog_getc (& c)) & & I

< count) { error= __put_user(c, buf); buf++; i++; } if (!error) error= i; /*返回实际读到的个数*/ return error; } static int mymsg_open(struct inode * inode, struct file * file) { mylog_r_tmp= mylog_r; return 0; } const struct file_operations proc_mymsg_operations = { .read= mymsg_read, .open= mymsg_open, }; static int mymsg_init(void) { struct proc_dir_entry *myentry; kmsg myentry= create_proc_entry("mymsg", S_IRUSR, &proc_root); if (myentry) myentry->

Proc_fops = & proc_mymsg_operations; return 0;} static void mymsg_exit (void) {remove_proc_entry ("mymsg", & proc_root);} module_init (mymsg_init); module_exit (mymsg_exit); / * name to kernel space * / EXPORT_SYMBOL (myprintk); MODULE_LICENSE ("GPL")

5. Test program

Note: EXPORT_SYMBOL (myprintk) is used in the above program; it means that myprintk can be used throughout kernel space.

How to use it:

① extern int myprintk (const char * fmt,...); statement

② myprintk ("first_drv_open:% d\ n", + + cnt); use the

# include # include static struct class * firstdrv_class; static struct class_device * firstdrv_class_dev; volatile unsigned long * gpfcon = NULL; volatile unsigned long * gpfdat = NULL; extern int myprintk (const char * fmt,...); static int first_drv_open (struct inode * inode, struct file * file) {static int cnt = 0; myprintk ("first_drv_open:% d\ n", + + cnt) / * configure GPF4,5,6 to output * / * gpfcon & = ~ (0x3)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report