5.2. Read and Write a /proc File

We have seen a very simple example for a /proc file where we only read the file /proc/helloworld. It's also possible to write in a /proc file. It works the same way as read, a function is called when the /proc file is written. But there is a little difference with read, data comes from user, so you have to import data from user space to kernel space (with copy_from_user or get_user)

The reason for copy_from_user or get_user is that Linux memory (on Intel architecture, it may be different under some other processors) is segmented. This means that a pointer, by itself, does not reference a unique location in memory, only a location in a memory segment, and you need to know which memory segment it is to be able to use it. There is one memory segment for the kernel, and one for each of the processes.

The only memory segment accessible to a process is its own, so when writing regular programs to run as processes, there's no need to worry about segments. When you write a kernel module, normally you want to access the kernel memory segment, which is handled automatically by the system. However, when the content of a memory buffer needs to be passed between the currently running process and the kernel, the kernel function receives a pointer to the memory buffer which is in the process segment. The put_user and get_user macros allow you to access that memory. These functions handle only one caracter, you can handle several caracters with copy_to_user and copy_from_user. As the buffer (in read or write function) is in kernel space, for write function you need to import data because it comes from user space, but not for the read function because data is already in kernel space.

Example 5-2. procfs2.c

/** a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html procfs2.c - create a "file" in /proc a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ #include <linux/module.h> /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var Specifically, a module figures/ #include <linux/kernel.h> /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var We're doing kernel work figures/ #include <linux/proc_fs.h> /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var Necessary because we use the proc fs figures/ #include <asm/uaccess.h> /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var for copy_from_user figures/ #define PROCFS_MAX_SIZE 1024 #define PROCFS_NAME "buffer1k" /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html This structure hold information about the /proc file a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ static struct proc_dir_entry *Our_Proc_File; /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html The buffer used to store character for this module a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ static char procfs_buffer[PROCFS_MAX_SIZE]; /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html The size of the buffer a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ static unsigned long procfs_buffer_size = 0; /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html This function is called then the /proc file is read a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ int procfile_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data) { int ret; printk(KERN_INFO "procfile_read (/proc/%s) called\n", PROCFS_NAME); if (offset > 0) { /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var we have finished to read, return 0 figures/ ret = 0; } else { /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var fill the buffer, return the buffer size figures/ memcpy(buffer, procfs_buffer, procfs_buffer_size); ret = procfs_buffer_size; } return ret; } /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html This function is called with the /proc file is written a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ int procfile_write(struct file *file, const char *buffer, unsigned long count, void *data) { /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var get buffer size figures/ procfs_buffer_size = count; if (procfs_buffer_size > PROCFS_MAX_SIZE ) { procfs_buffer_size = PROCFS_MAX_SIZE; } /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var write data to the buffer figures/ if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) { return -EFAULT; } return procfs_buffer_size; } /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var *This function is called when the module is loaded a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ int init_module() { /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var create the /proc file figures/ Our_Proc_File = create_proc_entry(PROCFS_NAME, 0644, NULL); if (Our_Proc_File == NULL) { remove_proc_entry(PROCFS_NAME, &proc_root); printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", PROCFS_NAME); return -ENOMEM; } Our_Proc_File->read_proc = procfile_read; Our_Proc_File->write_proc = procfile_write; Our_Proc_File->owner = THIS_MODULE; Our_Proc_File->mode = S_IFREG | S_IRUGO; Our_Proc_File->uid = 0; Our_Proc_File->gid = 0; Our_Proc_File->size = 37; printk(KERN_INFO "/proc/%s created\n", PROCFS_NAME); return 0; /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var everything is ok figures/ } /apps /backup /bin /boot /data /dev /etc /home /lib /lost+found /media /misc /mnt /net /opt /proc /root /sbin /selinux /srv /sys /tftpboot /tmp /usr /var *This function is called when the module is unloaded a1387.htm a1387.html a1403.htm a1403.html book1.htm c1050.htm c1050.html c1159.htm c1159.html c119.htm c119.html c1209.htm c1209.html c1254.htm c1324.htm c1324.html c1350.htm c1350.html c38.htm c38.html c425.htm c425.html c567.htm c567.html c708.htm c708.html c885.htm c885.html c890.htm c890.html c976.htm c976.html doc-index.html f25.htm f25.html figures hello2.html i1413.htm index.html interrupthandlers.html ln16.html TXT_lkmpg.html x1052.html x1161.html x1194.htm x1194.html x1211.html x121.html x1256.html x1326.html x1352.html x1389.html x1405.html x181.htm x181.html x217.htm x245.htm x245.html x279.htm x279.html x27.html x30.htm x30.html x323.htm x323.html x351.htm x351.html x35.htm x35.html x380.htm x380.html x40.html x427.html x44.htm x44.html x569.html x710.html x769.htm x769.html x810.htm x810.html x861.htm x861.html x887.html x892.html x978.html figures/ void cleanup_module() { remove_proc_entry(PROCFS_NAME, &proc_root); printk(KERN_INFO "/proc/%s removed\n", PROCFS_NAME); }