Linux kernel 始终在count bytes设置为零的情况下调用/proc/entry的write方法
我试图理解procfs的seq文件接口。我创建了一个小型内核模块,用于读取/写入proc条目。我写的模块是:Linux kernel 始终在count bytes设置为零的情况下调用/proc/entry的write方法,linux-kernel,kernel-module,Linux Kernel,Kernel Module,我试图理解procfs的seq文件接口。我创建了一个小型内核模块,用于读取/写入proc条目。我写的模块是: #define PROC_DIR_NAME "driver/kernel_test_dir2" #define KERNEL_DATA "This is kernel test" static struct proc_dir_entry *proc_entry_file = 0; static struct proc_dir_entry *proc_dir = 0; #define
#define PROC_DIR_NAME "driver/kernel_test_dir2"
#define KERNEL_DATA "This is kernel test"
static struct proc_dir_entry *proc_entry_file = 0;
static struct proc_dir_entry *proc_dir = 0;
#define PROC_ENTRY_BUFFER_SIZE 64
struct proc_entry
{
ssize_t buffer_length;
char buffer[PROC_ENTRY_BUFFER_SIZE];
};
static int proc_entry_seq_show(struct seq_file *s, void *v)
{
printk(KERN_INFO "kernel_test:proc_entry_seq_show\n");
struct proc_entry* kmem = s->private;
if(kmem)
{
printk(KERN_INFO "kernel_test:proc_entry_seq_show:s->private=%x\n",s->private);
seq_printf(s, "%s\n",&(kmem->buffer[0]));
}
return 0;
}
static int proc_entry_open(struct inode *inode, struct file *file)
{
struct proc_entry* kmem = kmalloc(sizeof(struct proc_entry),GFP_KERNEL);
return single_open(file,&proc_entry_seq_show,(void*)kmem);
};
static int proc_entry_close(struct inode *inode, struct file *file)
{
struct seq_file *s = file->private_data;
struct proc_entry* kmem = (struct proc_entry*)(s->private);
kfree(kmem);
return single_release(inode,file);
};
static ssize_t proc_entry_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
ssize_t len=0;
loff_t pos;
struct seq_file* seqfile = (struct seq_file*)(file->private_data);
printk(KERN_INFO "kernel_test:proc_entry_write\n");
printk(KERN_INFO "kernel_test:proc_entry_write:offset = %d, count=%d\n",*ppos,count);
if(seqfile)
{
printk(KERN_INFO "kernel_test:proc_entry_write:seqfile\n");
struct proc_entry* kmem = (struct proc_entry*)(seqfile->private);
if(kmem)
{
printk(KERN_INFO "kernel_test:proc_entry_write:kmem\n");
pos = *ppos;
if(pos<0)
return -EINVAL;
if(count > PROC_ENTRY_BUFFER_SIZE)
count = PROC_ENTRY_BUFFER_SIZE;
if(copy_from_user(&(kmem->buffer[0]), buf, count))
return -EFAULT;
(*ppos) = pos + count;
kmem->buffer_length = count;
return count;
}
printk(KERN_INFO "kernel_test:proc_entry_write:kmem does not exist!\n");
}
printk(KERN_INFO "kernel_test:proc_entry_write:seqfile does not exist!\n");
return -EFAULT;
}
static struct file_operations fops_proc_entry = {
.open = proc_entry_open,
.read = seq_read,
.release = proc_entry_close,
.write = proc_entry_write,
};
static int __init init_test_kernel(void) {
int rv;
proc_dir = proc_mkdir(PROC_DIR_NAME, NULL);
if(proc_dir == NULL) {
rv = -ENOMEM;
}
proc_entry_file = proc_create ("kernel_test_file", S_IRUSR | S_IWUSR, proc_dir,&fops_proc_entry);
if(!proc_entry_file) {
rv = -ENOMEM;
}
printk(KERN_INFO "kernel_test: Kernel Test module started\n");
return 0;
}
// Cleanup module
static void __exit cleanup_test_kernel(void) {
remove_proc_entry("kernel_test_file", proc_dir);
remove_proc_entry(PROC_DIR_NAME,NULL);
printk(KERN_INFO "kernel_test: Kernel Test module stopped\n");
}
module_init(init_test_kernel);
module_exit(cleanup_test_kernel);
似乎使用“count”的正确值正确调用了write函数。我没有使用单printk语句来编写多个变量值,而是对每个要打印的变量使用单printk,它可以正确地打印值。但是printf说明符
%d
指的是公共int
,在许多平台上是32位宽度。因此,printk
输出的不是计数变量作为第二个字段,而是其第一个参数的一部分,*ppos
。使用-Wall
编译模块会发现这些问题。谢谢Tsyvarev。我现在明白了。非常感谢您的输入。看来write函数调用正确,且“count”的值正确。我没有使用单printk语句来编写多个变量值,而是对每个要打印的变量使用单printk,它可以正确地打印值。但是printf说明符%d
指的是公共int
,在许多平台上是32位宽度。因此,printk
输出的不是计数变量作为第二个字段,而是其第一个参数的一部分,*ppos
。使用-Wall
编译模块会发现这些问题。谢谢Tsyvarev。我现在明白了。我感谢你的意见。
#define BUFFER_DATA "This is test kernel data by me"
#define MAX_BUFFER_SIZE 64
static char write_buffer[MAX_BUFFER_SIZE];
static char read_buffer[MAX_BUFFER_SIZE];
int main()
{
int fd;
int count=0;
fd = open("/proc/driver/kernel_test_dir2/kernel_test_file",O_RDWR);
if(fd<0)
{
std::cout <<"Could not open file /proc/driver/kernel_test_dir2/kernel_test_file !"<<
strerror(errno)<<std::endl;
return -1;
}
sprintf(write_buffer,"%s",BUFFER_DATA);
std::cout << "Write Buffer to be written is - "<<write_buffer<<std::endl;
count = write(fd,write_buffer,strlen(write_buffer));
std::cout << "The bytes requested to be written are - "<<strlen(write_buffer) <<std::endl;
if(count<0)
{
std::cout<<"write error : " << strerror(errno)<<std::endl;
return -1;
}
else if(count!=strlen(write_buffer))
{
std::cout<<"Wrote only "<<count<<" bytes, but was asked to write "<<strlen(write_buffer)<<" bytes"<<std::endl;
return -1;
}
count = read(fd,read_buffer,MAX_BUFFER_SIZE);
if(count < 0)
{
std::cout<<"read error : " << strerror(errno)<<std::endl;
return -1;
}
std::cout << "buffer read as - "<<read_buffer<<std::endl;
close(fd);
return 0;
}
Jun 20 16:03:51 kernel: [356787.943092] kernel_test:proc_entry_write
Jun 20 16:03:51 kernel: [356787.943554] kernel_test:proc_entry_write:offset = 0, count=0
Jun 20 16:03:51 kernel: [356787.943944] kernel_test:proc_entry_write:seqfile
Jun 20 16:03:51 kernel: [356787.944344] kernel_test:proc_entry_write:kmem
Jun 20 16:03:51 kernel: [356787.944978] kernel_test:proc_entry_seq_show
Jun 20 16:03:51 kernel: [356787.945408] kernel_test:proc_entry_seq_show:s->private=ee600600