1. Create file entries under /proc
1. Define the proc_dir_entry structure and the file_operations structure
1 //Define the entry structure of proc
2 static struct proc_dir_entry *myentry;
3
4 static struct file_operations proc_mymsg_operations = {
5 };
2. Create a proc entry in the entry function and associate it with the file_operations structure
1 static int mymsg_init(void)
2 {
3 //Create the proc directory
4 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
5
6 if(myentry)
7 myentry->proc_fops = &proc_mymsg_operations;
8
9 return 0;
10 }
3. In the export function, it is natural to delete the entry
1 static void mymsg_exit(void)
2 {
3 remove_proc_entry("mymsg", NULL);
4 }
4. Compile the test code and create a file mymsg in the /proc directory
Attach the driver mymsg_1.c
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 //Define the entry structure of proc
11 static struct proc_dir_entry *myentry;
12
13 static struct file_operations proc_mymsg_operations = {
14 };
15
16 static int mymsg_init(void)
17 {
18 //Create a proc directory
19 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
20
21 if(myentry)
22 myentry->proc_fops = &proc_mymsg_operations;
twenty three
24 return 0;
25 }
26
27 static void mymsg_exit(void)
28 {
29 remove_proc_entry("mymsg", NULL);
30 }
31
32 module_init(mymsg_init);
33 module_exit(mymsg_exit);
34
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("Lover Cher");
2. Implement read and write functions
Since our file_operations structure is empty, we naturally cannot read /proc/mymsg. Here we add a read function.
1 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
2 {
3 printk("mymsg_read n");
4 return 0;
5 }
6
7 static struct file_operations proc_mymsg_operations = {
8. read = mymsg_read,
9 };
After the compilation and loading is completed, we use the cat command to align and read. The result is as follows: It means that we have successfully entered the mymsg_read function.
Attach the driver mymsg_2.c
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 //Define the entry structure of proc
11 static struct proc_dir_entry *myentry;
12
13
14 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
15 {
16 printk("mymsg_read n");
17 return 0;
18 }
19
20
21 static struct file_operations proc_mymsg_operations = {
22. read = mymsg_read,
twenty three };
twenty four
25 static int mymsg_init(void)
26 {
27 //Create a proc directory
28 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
29
30 if(myentry)
31 myentry->proc_fops = &proc_mymsg_operations;
32
33
34 return 0;
35 }
36
37 static void mymsg_exit(void)
38 {
39 remove_proc_entry("mymsg", NULL);
40 }
41
42 module_init(mymsg_init);
43 module_exit(mymsg_exit);
44
45 MODULE_LICENSE("GPL");
46 MODULE_AUTHOR("Lover Cher");
3. Simulate memory data reading
Since we need to read, we naturally need to copy and print the data. Here we use the array to simulate the buff of the data, and then format the data in the init function to simulate writing data.
Then we read it in the mymsg_read function to see if the data can be read successfully.
1. Define a memory buff array
1 //Define the entry structure of proc
2 static struct proc_dir_entry *myentry;
3 static char mylog_buf[1024]; //data buffer
2. Format the string in the init function to simulate writing data
1 static int mymsg_init(void)
2 {
3 sprintf(mylog_buf, "%s", "abcdefghijklmnn"); //Simulate the data of forged buf
4 //Create a proc directory
5 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
6
7 if(myentry)
8 myentry->proc_fops = &proc_mymsg_operations;
9
10 return 0;
11 }
3. Read it in the mymsg_read function
1 //Implement the read function
2 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
3 {
4 if(copy_to_user(buf, mylog_buf, 10));
5 return 10;
6 }
4. Compile test: It is found that the data is read successfully.
Attach the driver mymsg_3.c
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9
10 //Define the entry structure of proc
11 static struct proc_dir_entry *myentry;
12 static char mylog_buf[1024]; //data buffer
13
14 //Implement the read function
15 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
16 {
17 //int cnt;
18 //printk("mymsg_read n");
19 // copy_to_user the data in mylog_buf, return
20 //cnt = min(1024,count);
21 if(copy_to_user(buf, mylog_buf, 10));
twenty two
23 return 10;
twenty four }
25
26 //Define file_operation structure
27 static struct file_operations proc_mymsg_operations = {
28. read = mymsg_read,
29 };
30
31 static int mymsg_init(void)
32 {
33 sprintf(mylog_buf, "%s", "abcdefghijklmnn"); //Simulate the data of forged buf
34 //Create a proc directory
35 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
36
37 if(myentry)
38 myentry->proc_fops = &proc_mymsg_operations;
39
40 return 0;
41 }
42
43 static void mymsg_exit(void)
44 {
45 remove_proc_entry("mymsg", NULL);
46 }
47
48 module_init(mymsg_init);
49 module_exit(mymsg_exit);
50
51 MODULE_LICENSE("GPL");
52 MODULE_AUTHOR("Lover Cher");
53
54
55 /*
56 1. Ring Buffer
57 Empty: R == W
58 write: buf[W] = val;
59 W = (W+1) % 10;
60 Read: val = buf[R]
61 R = (R+1) % 10
62 2.
63
64
65
66
67
68
69
70
71
72
73 */
4. Refer to the printk function, which can be used to print and save messages
Now let's write a myprintk function similar to printk, so that other drivers can call myprintk to output all the print information to /proc/mymsg.
It is convenient to debug the driver's printing information in a unified manner without being interfered by other printing information.
For the test driver, we use the previous imx257 LED driver:
Blog article address: http://www.cnblogs.com/lihaiyan/p/4297923.html
Of course, the same applies to other drivers. Just declare the myprintk function externally and then replace all printk with myprintk.
1. Define two data buffs, read and write pointers, and a waiting queue
1 //Define the entry structure of proc
2 static struct proc_dir_entry *myentry;
3 static char mylog_buf[MYLOG_BUF_LEN]; //data buffer
4 static char tmp_buf[MYLOG_BUF_LEN]; //data buffer
5 static int mylog_r = 0;
6 static int mylog_w = 0;
7
8 static DECLARE_WAIT_QUEUE_HEAD(mylog_wait);
2. Implement a function to determine if buff is empty
1 //Judge whether it is empty
2 static int is_mylog_empty(void)
3 {
4 return (mylog_r == mylog_w);
5 }
3. Implement a function to determine whether the buff is full
1 //Judge whether it is full
2 static int is_mylog_full(void)
3 {
4 return (((mylog_w + 1) % MYLOG_BUF_LEN) == mylog_r);
5 }
4. Implement the function of writing characters to buff
1 //Write characters
2 static void mylog_putc(char c)
3 {
4 if(is_mylog_full)
5 {
6 //Discard a data
7 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
8 }
9 mylog_buf[mylog_w] = c;
10 mylog_w = (mylog_w + 1) % MYLOG_BUF_LEN;
11
12 /* Wake up the process waiting for data */
13 wake_up_interruptible(&mylog_wait);
14 }
In addition to writing to buff, the function also has an important task of waking up the process so that the data can be printed out in the read function.
5. Implement the function to read buff characters
1 //Read characters
2 static int mylog_getc(char *p)
3 {
4 if(is_mylog_empty())
5 return 0;
6 *p = mylog_buf[mylog_r];
7 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
8 return 1;
9 }
6. Refer to the sprinf function of vsprintf.c in the kernel code, implement the myprintk function, and export the myprintk function for use by other programs
//Print output Refer to sprintf in vsprintf.c
int myprintk(const char *fmt, ...)
{
va_list args;
int i,j;
va_start(args, fmt);
i = vsnprintf(tmp_buf, INT_MAX, fmt, args);
va_end(args);
for(j = 0; j
{
mylog_putc(tmp_buf[j]);
}
return 1;
}
EXPORT_SYMBOL(myprintk);
7. Improve the read function
//Realize the read function, refer to kmsg.c
static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
{
int error;
int i = 0; //The number of data read
char c;
//Open with non-blocking mode and the data queue is empty
if ((file->f_flags & O_NONBLOCK) && is_mylog_empty())
return -EAGAIN;
//Wait until the queue is not empty
Previous article:Debug analysis: PC pointer analysis error based on kernel error information
Next article:iMX257 pin configuration function/memory read and write function
Recommended ReadingLatest update time:2024-11-14 15:22
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Red Hat announces definitive agreement to acquire Neural Magic
- 5G network speed is faster than 4G, but the perception is poor! Wu Hequan: 6G standard formulation should focus on user needs
- SEMI report: Global silicon wafer shipments increased by 6% in the third quarter of 2024
- OpenAI calls for a "North American Artificial Intelligence Alliance" to compete with China
- OpenAI is rumored to be launching a new intelligent body that can automatically perform tasks for users
- Nidec Intelligent Motion is the first to launch an electric clutch ECU for two-wheeled vehicles
- Nidec Intelligent Motion is the first to launch an electric clutch ECU for two-wheeled vehicles
- ASML provides update on market opportunities at 2024 Investor Day
- Arm: Focusing on efficient computing platforms, we work together to build a sustainable future
- AMD to cut 4% of its workforce to gain a stronger position in artificial intelligence chips
- Where are charge pumps generally used?
- Deep learning framework PyTorch: Getting started and practice
- Prize-winning quiz: Audio signal solution based on A2B
- The last two days of the exhibition will have prizes! ON Semiconductor will showcase its outstanding image perception solutions at the Machine Vision Exhibition (Shenzhen)
- How does BUCK output negative pressure?
- Op amp feedback resistor selection problem
- Forwarded article: A Complete Guide to Convolutional Neural Networks (CNN). It is well written.
- Convert an idle power adapter into an adjustable power supply
- I have been tinkering with Dahua cameras these days, and it took me a long time to even set up a network.
- 【Chuanglong Technology Allwinner A40i Development Board】TL7606I module test