昨天看完操作系统教材的第二章,今天抽了一点空余时间做一做课后的编程习题。
主要是简单练习一下Linux内核数据结构的链表。
问题非常简单,就是在模块加载的时候生成包含5个节点的双链表,然后,在模块卸载的时候,遍历5个节点,然后释放。
但是之前没怎么接触这类问题,刚开始的时候还是僵持了一下。好在链表管理的接口函数能够找见,对于解决问题真是帮助不小。
/usr/src/linux-2.6.39.4/include/linux/list.h
#include<linux/init.h>
#include<linux/kernel.h>
#include<list.h>
#include<linux/types.h>
#define NODE_NUM 5
#define _FL_ __FILE__, __LINE__
/*
** define the structure
*/
typedef struct birthday
{
int day;
int month;
int year;
struct list_head list;
} Birthday;
/*
** operation: generate a node
*/
Birthday* generate_node(void);
/*
** initialize a list named birthday_list
** note: the macro function is in linux/list.h
*/
LIST__HEAD(birthday_list);
/*
** This function is called when the module is loaded
*/
int simple_init(void)
{
long i = 0;
Birthday *person;
printk(KERN_INFO "Loading Module\n");
for(i = 0; i < NODE_NUM; i++)
{
/*
** generate a node firstly
*/
person = generate_node();
if(NULL == person)
return -1;
printk(KERN_INFO "person %02ld: born on %4d-%02d-%02d\n",
(i + 1), person->year, person->month, person->day);
/*
** append the node to the list birthday_list
** note: this function is in linux/list.h
*/
list_add_tail(&person->list, &birthday_list);
}
return 0;
}
/*
** This function is called when the module is removed
*/
void simple_exit(void)
{
Birthday *ptr, *next;
long i = 0;
printk(KERN_INFO "Removing Module\n");
list_for_each_entry_safe(ptr, next, &birthday_list, list)
{
printk(KERN_INFO "Removing person %02ld: %4d-%02d-%02d\n",
(i + 1), ptr->year, ptr->month, ptr->day);
list_del(&ptr->list);
kfree(ptr);
i++;
}
}
/*
** operation: generate a node
** input: nothing
** output: pointer to the struct birthday
*/
Birthday*
generate_node(void)
{
Birthday *ptr_birth;
ptr_birth = kmalloc(sizeof(*ptr_birth), GFP_KERNEL);
if(NULL == ptr_birth)
{
printk(KERN_INFO "[%s:%d]kmalloc error!\n", _FL_)
return ptr_birth;
}
ptr_birth->month = 8;
ptr_birth->year = 1995;
ptr_birth->day =2;
INIT_LIST_HEAD(&ptr_birth->list);
return ptr_birth;
}
/*
** registering module entry and exit points
*/
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple Module");
MODULE_AUTHOR("Jack Liu");
验证:
1.清空系统日志
sudo dmesg -c
2.加载模块
sudo insmod simple.ko
3.卸载模块
sudo rmmod simple