The problem is that when reading from the file, the message "killed" crashes. There is a thought that something is wrong with reading. But what? And who knows ... Here is the code:

#include <linux/kernel.h> #include <linux/sched.h> #include <linux/module.h> #include <linux/string.h> #include <linux/syscalls.h> #include <linux/vmalloc.h> #include <linux/proc_fs.h> #include <asm/uaccess.h> #include <linux/cdev.h> #include <linux/seq_file.h> #include <linux/slab.h> #define TASKLIST "tasklist" #define TASKS "tasks" int open_proc(struct inode *inode, struct file *file); int open_proc_message(void); ssize_t read_proc (struct seq_file *m, void *v); int create_task_entry(void); ssize_t write_proc(struct file *filp, const char *buf, size_t count, loff_t *offp); static struct proc_dir_entry *proc_entry; static struct proc_dir_entry *dir_entry; static char *msg = "hello"; struct file_operations file_fops = { .owner = THIS_MODULE, .open = open_proc, .read = read_proc, .write = write_proc, .release = single_release, }; int create_task_entry(void) { int ret = 0; if(!(dir_entry = proc_mkdir(TASKLIST, NULL))){ printk(KERN_INFO "Can't create the directory %s. Bye\n", TASKLIST); ret = -ENOMEM; } //create file if (!(proc_entry = proc_create(TASKS, 0664, dir_entry, &file_fops))) { remove_proc_entry(TASKLIST, NULL); ret = -ENOMEM; } return ret; } int open_proc(struct inode *inode, struct file *file) { return single_open(file, read_proc, NULL); } ssize_t read_proc (struct seq_file *m, void *v) { if (msg) seq_printf(m,"%s\n", msg); return 0; } int open_proc_message(void) { printk(KERN_ALERT "File was opened!\n\n"); return 0; } int init_module(void) { return create_task_entry(); } void cleanup_module(void){ printk(KERN_INFO "Cleaning Up.\n"); remove_proc_entry(TASKLIST, NULL); remove_proc_entry(TASKS,NULL); } ssize_t write_proc(struct file *filp, const char *buf, size_t count, loff_t *offp){ msg = (char*)kmalloc(255 * sizeof(char), GFP_KERNEL); copy_from_user(msg, buf, count); return count; } 
  • one
    seq_ * is a new interface for me, before there was no such thing and read worked like write, only copy_to_user. Here I look at the source of the kernel. And I see that in the case of using seq_ * in file_opertions, always .read = seq_read is transferred, and not its own handler and the function of opening the file is more complicated than yours. If you hang your handler on read, then its parameters are completely different, similar to those of your write. And there are no seq_file there, but there is no trace. seq_file is passed to a handler that apparently calls seq_read, by registering with seq_open using the seq_operations structure - Mike
  • Well, you have a memory leak at write, you allocate memory and you don’t release it anywhere - Mike

1 answer 1

Redid the entry in / proc. Reading this file from user space is correct. Here is the code:

  #include <linux/kernel.h> #include <linux/sched.h> #include <linux/module.h> #include <linux/string.h> #include <linux/syscalls.h> #include <linux/vmalloc.h> #include <linux/proc_fs.h> #include <asm/uaccess.h> #include <linux/cdev.h> int create_proc_entry(void); static int tasks_proc_show(struct seq_file *m, void *v); static int tasks_proc_open(struct inode *inode, struct file *file); static const struct file_operations file_fops = { .open = tasks_proc_open, .read = seq_read, .write = seq_write, .llseek = seq_lseek, .release = single_release, }; static int tasks_proc_show(struct seq_file *m, void *v){ struct task_struct *task = &init_task; while((task = next_task(task))!= &init_task) seq_printf(m,"%s %d\n",task->comm, task->pid); return 0; } static int tasks_proc_open(struct inode *inode, struct file *file){ single_open(file, tasks_proc_show, NULL); } int proc_init(void) { proc_create("ltask",0,NULL,&file_fops); return 0; } void proc_cleanup(void) { remove_proc_entry("ltask",NULL); } MODULE_LICENSE("GPL"); module_init(proc_init); module_exit(proc_cleanup);