清单 10. 对 fortune 进行写入操作所使用的函数
ssize_t fortune_write( struct file *filp, const char __user *buff,
unsigned long len, void *data )
{
int space_available = (MAX_COOKIE_LENGTH-cookie_index)+1;
if (len 》 space_available) {
printk(KERN_INFO “fortune: cookie pot is full!\n”);
return -ENOSPC;
}
if (copy_from_user( &cookie_pot[cookie_index], buff, len )) {
return -EFAULT;
}
cookie_index += len;
cookie_pot[cookie_index-1] = 0;
return len;
}
对 fortune 进行读取也非常简单,如清单 11 所示。由于我们刚才写入数据的缓冲区(page)已经在内核空间中了,因此可以直接对其进行操作,并使用 sprintf 来写入下一个 fortune。如果 next_fortune 索引大于 cookie_index(要写入的下一个位置),那么我们就将 next_fortune 返回为 0,这是第一个 fortune 的索引。在将这个 fortune 写入用户缓冲区之后,在 next_fortune 索引上增加刚才写入的 fortune 的长度。这样就变成了下一个可用 fortune 的索引。这个 fortune 的长度会被返回并传递给用户。
清单 11. 对 fortune 进行读取操作所使用的函数
int fortune_read( char *page, char **start, off_t off,
int count, int *eof, void *data )
{
int len;
if (off 》 0) {
*eof = 1;
return 0;
}
/* Wrap-around */
if (next_fortune 》= cookie_index) next_fortune = 0;
len = sprintf(page, “%s\n”, &cookie_pot[next_fortune]);
next_fortune += len;
return len;
}
从这个简单的例子中,我们可以看出通过 /proc 文件系统与内核进行通信实际上是件非常简单的事情。现在让我们来看一下这个 fortune 模块的用法(参见清单 12)。
清单 12. 展示 fortune cookie LKM 的用法
[root@plato]# insmod fortune.ko [root@plato]# echo “Success is an individual proposition.
Thomas Watson” 》 /proc/fortune [root@plato]# echo “If a man does his best, what else is there?
Gen. Patton” 》 /proc/fortune [root@plato]# echo “Cats: All your base are belong to us.
Zero Wing” 》 /proc/fortune [root@plato]# cat /proc/fortune Success is an individual proposition. Thomas Watson
[root@plato]# cat /proc/fortune If a man does his best, what else is there? General Patton
[root@plato]#
/proc 虚拟文件系统可以广泛地用来报告内核的信息,也可以用来进行动态配置。