https://www.ibm.com/developerworks/cn/linux/l-kerns-usrs2/
First, Procfs
PROCFS is a relatively old user state and the kernel state of data exchange, the kernel of a lot of data is exported to the user in this way, many of the kernel parameters are also in this way to allow users to easily set. Most of the kernel parameters provided by PROCFS are read-only, except for the sysctl exit to/proc parameters. In fact, many applications rely heavily on PROCFS, so it's almost an essential component. Several examples in the previous section actually used it to export kernel data, but did not explain how to use it, and this section explains how to use PROCFS.
PROCFS provides the following APIs:
1 2 |
struct Proc_dir_entry *create_proc_entry (const char *name, mode_t mode, struct Proc_dir_entry *parent) |
This function is used to create a normal proc entry, parameter name gives the name of the proc entry to be established, parameter mode gives access to the established proc entry, and the argument parent specifies the directory where the proc entry is established. If you want to create a proc entry under/proc, parent should be null. Otherwise it should be a pointer to the struct PROC_DIR_ENTRY structure returned by Proc_mkdir.
1 |
extern void Remove_proc_entry (const char *name, struct proc_dir_entry *parent) |
This function deletes the proc entry created by the function above, the parameter name gives the name of the proc entry to be deleted, and the parameter parent specifies the directory where the proc entry is established.
1 |
struct Proc_dir_entry *proc_mkdir (const char * name, struct proc_dir_entry *parent) |
This function is used to create a proc directory in which the parameter name specifies the name of the proc directory to be created, and the parameter parent is the directory where the proc directory resides.
1 2 3 4 |
extern struct Proc_dir_entry *proc_mkdir_mode (const char *name, mode_t mode, struct PROC_DIR_ENTR Y *parent); struct Proc_dir_entry *proc_symlink (const char * name, struct proc_dir_entry * parent, const char * dest) |
This function is used to establish a symbolic link for a proc entry, parameter name gives the name of the symbolic link proc entry to be established, parameter parent specifies the directory in which the symbolic connection is located, and the parameter dest specifies the proc entry name to link to.
1 2 3 |
struct Proc_dir_entry *create_proc_read_entry (const char *name, mode_t mode, struct proc_dir_entry, *base, read_proc_t *read_proc, void * data) |
This function is used to establish a read-only proc entry for a rule, parameter name gives the name of the proc entry to be established, and argument mode gives access to the established proc entry, parameter base specifies the directory where the proc entry is established, and the parameter Read_ Proc gives the action function to read the proc entry, the parameter data is the private data for the proc entry, and it is saved in the struct field of the Private_data file structure corresponding to the proc entry.
1 2 |
struct Proc_dir_entry *create_proc_info_entry (const char *name, mode_t mode, struct proc_dir_entry, *base o_t *get_info) |
This function is used to create an info-type proc entry, parameter name gives the name of the proc entry to be established, parameter mode gives access to the established proc entry, and the parameter base specifies the directory where the proc entry is established, and the parameter get_ INFO Specifies the Get_info action function for the proc entry. In fact, Get_info is equivalent to Read_proc, and if the proc entry does not define a read_proc, the read operation on the proc entry will be replaced with get_info, so it is functionally very similar to the function Create_proc_read_ Entry
1 2 |
struct Proc_dir_entry *proc_net_create (const char *name, mode_t mode, get_info_t *get_info) |
This function is used to create a proc entry in the/proc/net directory, parameter name gives the name of the proc entry to be established, argument mode gives access to the established proc entry, and the parameter get_info specifies the proc operation function of the Get_info entry.
1 2 |
struct Proc_dir_entry *proc_net_fops_create (const char *name, mode_t mode, struct file_operations) |
The function is also used to create a proc entry under/proc/net, but it also specifies the file action function for the proc entry.
1 |
void Proc_net_remove (const char *name) |
This function deletes the proc entry created by the previous two functions under the/proc/net directory. The parameter name specifies the name of the proc to delete.
In addition to these functions, it is worth mentioning that the structure struct proc_dir_entry, in order to create a writable proc entry and specify the write operation function of the proc entry, you must set the top of these proc entries to the function returned by the pointer to the struct PROC_DIR _entry the Write_proc field of the structure and specifies that the access rights of the proc entry have write permissions.
In order to use these interface functions and the structure struct proc_dir_entry, the user must include the header file Linux/proc_fs.h in the module.
The PROCFS sample program PROCFS_EXAM.C, which defines three proc file entries and a proc directory entry, is given in the source code package, and the reader should see the following structure after inserting the module :
1 2 3 |
$ ls/proc/myproctest aint astring bigprocfile $ |
Readers can view and set these proc files by using file manipulation functions such as Cat and Echo. In particular, it should be noted that Bigprocfile is a large file (more than a page of memory), for this large file, PROCFS has some limitations, because it provides the cache, only one page, so must be particularly careful, and for more than the pages of the section to do a special consideration, processing more complex and error prone, All PROCFS are not suitable for large amount of data input and output, the following section Seq_file is designed for this flaw, of course, Seq_file relies on some of PROCFS basic functions. Second, Seq_file
In general, the kernel provides output information to user space by creating files under the Procfs file system, and user space can view the file information through any text-reading application, but PROCFS has a flaw that if the output is larger than 1 pages, it needs to be read multiple times, so it is difficult to handle and, in addition, If the output is too large, the speed is slow, sometimes some unexpected situation, Alexander Viro implement a new set of functions, make the kernel output large file information easier, This feature is available in all 2.4 cores and 2.6 cores after 2.4.15 (including 2.4.15), especially in the 2.6 kernel, which has been used extensively.
To use the Seq_file feature, the developer needs to include the header file Linux/seq_file.h and define and set up a seq_operations structure (similar to the file_operations structure):
1 2 3 4 5 6 |
struct Seq_operations {void * (*start) (struct seq_file *m, loff_t *pos); void (*stop) (struct seq_file *m, void *v); void * (*next) (struct seq_file *m, void *v, loff_t *pos); Int (*show) (struct seq_file *m, void *v); }; |
The start function specifies the read start position of the Seq_file file, returns the actual read start position, and if the specified position exceeds the end of the file, the Null,start function can have a special return Seq_start_token, which is used to let the show function output the file header. However, this can only be used when POS is 0, and the next function is used to move the current read position of the Seq_file file to the next read position, returning the actual next read position, and if the end of the file is reached, the Null,stop function is used to call after the Seq_file file is read. It is similar to the file operation close, which is used to do some necessary cleanup, such as freeing memory, and so on, the show function is used to format the output, or the error code is returned if 0 is successfully returned.
Seq_file also defines a number of auxiliary functions for formatting output:
1 |
int SEQ_PUTC (struct seq_file *m, char c); |
function SEQ_PUTC is used to output a character to a seq_file file.
1 |
int seq_puts (struct seq_file *m, const char *s); |
function seq_puts is used to output a string to a Seq_file file.
1 |
int Seq_escape (struct seq_file *, const char *, const char *); |
The function seq_escape is similar to seq_puts, except that it will output the characters contained in the second string argument in the first string argument in octal form, or the characters are escaped.
1 2 |
int seq_printf (struct seq_file *, const char *, ...) __ATTRIBUTE__ (Format (printf,2,3)); |
Function seq_printf is the most commonly used output function, which is used to output a given parameter to a seq_file file in the given format.
1 |
int Seq_path (struct seq_file *, struct vfsmount *, struct dentry *, char *); |
function Seq_path is used for output file names, and string arguments provide file name characters that need to be escaped, which are primarily used by the file system.
After defining the structure struct seq_operations, the user also needs to turn on the open function of the Seq_file file so that the structure is associated with the struct file structure corresponding to seq_file files, for example, struct seq_ Operations is defined as :
1 2 3 4 5 6 |
struct Seq_operations exam_seq_ops = {. Start = Exam_seq_start,. Stop = Exam_seq_stop,. Next = Exam_seq_next, . Show = Exam_seq_show}; |
Then the open function should be defined as follows:
1 2 3 4 |
static int Exam_seq_open (struct inode *inode, struct file *file) {return Seq_open (file, &exam_seq_ops); |
Note that the function Seq_open is a function provided by Seq_file, which is used to associate the struct seq_operations structure with the Seq_file file. Finally, the user needs to set the struct file_operations structure as follows:
1 2 3 4 5 6 7 |
struct File_operations exam_seq_file_ops = {. Owner = This_module,. Open = Exm_seq_open,. Read = Seq_read,. Llseek = Seq_lseek,. Release = Seq_release}; |
Note that the user only needs to set the open function, and the rest is the function provided by Seq_file.
The user then creates a/proc file and sets its file action to Exam_seq_file_ops:
1 2 3 4 |
struct Proc_dir_entry *entry; Entry = Create_proc_entry ("Exam_seq_file", 0, NULL); if (entry) Entry->proc_fops = &exam_seq_file_ops; |
For simple output, seq_file users do not need to define and set so many functions and structs, it just needs to define a show function, and then use Single_open to define the open function, and here are the general steps to use this simple form:
1. Define a show function
1 2 3 4 |
int exam_show (struct seq_file *p, void *v) {...} |
2. Define the Open function
1 2 3 4 |
int Exam_single_open (struct inode *inode, struct file *file) {return (Single_open (file, Exam_show, NULL)); |
Be careful to use single_open instead of Seq_open.
3. Define struct file_operations structure