"Generally, the kernel provides output information to the user space by creating files under the PROCFS file system. The user space can view the file information through any text reading application, but PROCFS has a defect. If the output content is greater than one memory page, it needs to be read multiple times, so it is difficult to process. In addition, if the output is too large and the speed is slow, Sometimes some unexpected situations occur. Alexander viro implements a new set of functions to make it easier for the kernel to output large file information. This function appears in all 2.4 kernels and 2.6 kernels after 2.4.15 (including 2.4.15), especially in 2.6 kernels, which has been widely used.
To use seq_ File function, developers need to include the header file Linux / SEQ_ File. H, and define and set an SEQ_ Operations structure (similar to file)_ Operations structure:
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 SEQ_ The read start position of the file returns the actual read start position. If the specified position exceeds the end of the file, it should return null. The start function can have a special return SEQ_ START_ Token, which is used to let the show function output the file header, but this can only be used when POS is 0, and the next function is used to put SEQ_ The current read position of the file is moved to the next read position, and the actual next read position is returned. If the end of the file has been reached, null is returned. The stop function is used to read SEQ after reading_ After the file file is invoked, it is similar to the file operation close. It is used to do some necessary cleaning, such as freeing memory. The show function is used for formatting output. If it returns 0 successfully, it will return error code.
Seq_ File also defines some auxiliary functions for formatting output:
/*Function seq_ Putc is used to output a character to SEQ_ File file*/
int seq_ putc(struct seq_ file *m, char c);
/*Function seq_ Puts is used to output a string to SEQ_ File file*/
int seq_ puts(struct seq_ file *m, const char *s);
/*Function seq_ Escape is similar to SEQ_ Put, just, it will include what appears in the first string parameter in the second string parameter
The characters in are output in octal form, that is, these characters are escaped*/
int seq_ escape(struct seq_ file *, const char *, const char *);
/*Function seq_ Printf is the most commonly used output function, which is used to output a given parameter to SEQ according to a given format_ File file*/
int seq_ printf(struct seq_ file *, const char *, ...)__ attribute__ (( format(printf,2,3)));
/*Function seq_ Path is used to output the file name. The string parameter provides the file name characters that need to be escaped. It is mainly used by the file system*/
int seq_ path(struct seq_ file *, struct vfsmount *, struct dentry *, char *);
After defining the structure struct seq_ After operations, the user also needs to open SEQ_ The open function of the file so that the structure corresponds to SEQ_ The struct file structure of the file file is associated, for example, struct SEQ_ Operations are defined as:
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:
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 SEQ_ File, which is used to put struct seq_ Operations structure and seq_ File.
Finally, you need to set struct file as follows_ Operations structure:
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 others are SEQ_ File.
The user then creates a / proc file and sets its file operation to exam_ seq_ file_ Ops:
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 structures. They only need to define a show function and then use single_ Open to define the open function. The following are the general steps to use this simple form:
1. Define a show function
int exam_ show(struct seq_ file *p, void *v)
{
…
}
2. Define the open function
int exam_ single_ open(struct inode *inode, struct file *file)
{
return(single_ open(file, exam_ show, NULL));
}
Note the use of single_ Open instead of SEQ_ open。
3. Define struct file_ Operations structure
struct file_ operations exam_ single_ seq_ file_ operations = {
.open = exam_ single_ open,
.read = seq_ read,
.llseek = seq_ lseek,
.release = single_ release,
};
Note that if the open function uses single_ Open, release function must be single_ Release, not seq_ release。 Here is an example of using SEQ_ File specific example seqfile_ Exam. C, which uses SEQ_ File provides a / proc interface to view all processes running in the current system. After compiling and inserting the module, the user can use the command "cat / proc / exam"_ esq_ "File" "can view all processes of the system.".
//kernel module: seqfile_ exam.c
#include
#include
#include
#include
#include
#include
static struct proc_ dir_ entry *entry;
static void *l_ start(struct seq_ file *m, loff_ t * pos)
{
loff_ t index = *pos;
if (index == 0) {
seq_ printf(m, ""Current all the processes in system:\n""
""%-24s%-5s\n"", ""name"", ""pid"");
return &init_ task;
}
else {
return NULL;
}
}
static void *l_ next(struct seq_ file *m, void *p, loff_ t * pos)
{
task_ t * task = (task_ t *)p;
task = next_ task(task);
if ((*pos != 0) && (task == &init_ task)) {
return NULL;
}
++*pos;
return task;
}
static void l_ stop(struct seq_ file *m, void *p)
{
}
static int l_ show(struct seq_ file *m, void *p)
{
task_ t * task = (task_ t *)p;
seq_ printf(m, ""%-24s%-5d\n"", task->comm, task->pid);
return 0;
}
static struct seq_ operations exam_ seq_ op = {
.start = l_ start,
.next = l_ next,
.stop = l_ stop,
.show = l_ show
};
static int exam_ seq_ open(struct inode *inode, struct file *file)
{
return seq_ open(file, &exam_ seq_ op);
}
static struct file_ operations exam_ seq_ fops = {
.open = exam_ seq_ open,
.read = seq_ read,
.llseek = seq_ lseek,
.release = seq_ release,
};
static int __ init exam_ seq_ init(void)
{
entry = create_ proc_ entry(""exam_ esq_ file"", 0, NULL);
if (entry)
entry->proc_ fops = &exam_ seq_ fops;
return 0;
}
static void __ exit exam_ seq_ exit(void)
{
remove_ proc_ entry(""exam_ esq_ file"", NULL);
}
module_ init(exam_ seq_ init);
module_ exit(exam_ seq_ exit);
MODULE_ LICENSE(""GPL"");, Read the full text“
Our other product: