把自己认为有保留价值的几个代码片断给放在这里,以供参考!
1.进行proc文件系统编程,在内核中维护一张表格(表格记录了学生的姓名和学号),可以向表格添加记录,显示记录和删除记录,并编写一个用户程序进行测试
老师给的答案(好像有问题):
/*
* a mini module do nothing
* test passed on linux redhat 9 'kernel 2.4.20-8'
* Compile:
* gcc -c -I/usr/src/linux/include -Wall procf.c
*/
//#define __NO_VERSION__
#define LINUX
#define __KERNEL__
#define MODULE
#include <linux/kernel.h> /* program in kernel */
#include <linux/module.h> /* program as module */
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define KBUILD_MODNAME procf
char content[100] = "this my file content";
int len = 20;
int my_read_proc(char *buf, char **start, off_t offset, int xlen, int *eof, void *data)
{
//copy_to_user(buf, content, len);
int i;
for(i=0; i<len+1; i++) buf[i] = content[i];
return len;
}
int my_write_proc(struct file *file, const char *buf,
unsigned long count, void *data)
{
int i;
if( count > 99 ) count = 99;
//copy_from_user(content, buf, count);
for(i=0; i<count; i++) content[i] = buf[i];
len = i;
content[i] = '\0';
return len;
}
struct proc_dir_entry my_entry = {
0,
6, /* unsigned short namelen */
"myname", /* const char *name */
S_IFREG | S_IRUGO, /* mode_t mode */
1, /* nlink_t nlink */
0, /* uid_t uid */
0, /* gid_t gid */
2, /* unsigned long size */
NULL, /* struct inode_operations *ops */
NULL,
NULL,
NULL, NULL, NULL,
NULL,
my_read_proc,
my_write_proc,
NULL,
0,
0
};
int init_module()
{
int i;
for(i=49, len =0; i<59; i++){
content[i-49] = i;
len ++;
}
content[i] = '\0';
proc_register(&proc_root, &my_entry);
printk("Hello world\n");
return 0;
}
void cleanup_module()
{
proc_unregister(&proc_root, my_entry.low_ino);
printk("bye\n");
}
MODULE_LICENSE("GPL");
自己改造过的答案:
#define LINUX
#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
//#include <string.h>
//#include <stdio.h>
#define NAMELEN 10
#define IDLEN 10
#define STRINGLEN 100
struct person_information{
char name[NAMELEN];
char id[IDLEN];
};
char global_buffer[1024];
struct person_information global_buffer_student[STRINGLEN];
//struct proc_dir_entry student_file = {
//0,
//strlen("student_file"), /*unsigned short namelen*/
//"student_file",/*const char* name*/
//S_IFREG|S_IRUGO,/*mode_t mode*/
//1,/*nlink_t nlink*/
//0,/*uid_t uid*/
//0,/*gid_t gid*/
//2,/*unsigned long size*/
//NULL,/*struct inode_operation *pos*/
//NULL,
//NULL,
//NULL,NULL,NULL,
//NULL,
//proc_read_student,
//proc_write_student,
//NULL,
//0,
//0
//};
struct proc_dir_entry *student_file;
struct proc_dir_entry *example_dir;
struct proc_dir_entry *current_file;
struct proc_dir_entry *hello_file;
struct proc_dir_entry *symlink;
int proc_read_student(char* page,char** start,off_t off,int count,int* eof,void* data);
int proc_write_student(struct file *file,const char *buffer,unsigned long count,void* data);
int proc_read_current(char* page,char** start,off_t off,int count,int *eof,void* data);
int proc_read_hello(char* page,char** start,off_t off,int count,int* eof,void* data);
int proc_write_hello(struct file *file,const char *buffer,unsigned long count,void* data);
void init_student(){
int i=0;
for(i;i<STRINGLEN;++i){
memset(global_buffer_student[i].name,'0'+i,NAMELEN);
memset(global_buffer_student[i].id,i,IDLEN);
}
}
int proc_read_student(char* page,char** start,off_t off,int count,int* eof,void* data){
int len;
MOD_INC_USE_COUNT;
len = sprintf(page,"golbal_buffer==%s\n",global_buffer);
int i;
//init_student();
i=0;
//for(i=0;i<STRINGLEN;++i){
printk("name==%s,id==%s\n",global_buffer_student[i].name,global_buffer_student[i].id);
//}
MOD_DEC_USE_COUNT;
return len;
}
int proc_write_student(struct file *file,const char *buffer,unsigned long count,void* data){
int len;
MOD_INC_USE_COUNT;
if(count>=STRINGLEN)
len = STRINGLEN-1;
else
len = count;
copy_from_user(global_buffer_student,buffer,len);
global_buffer[len]='\0';
MOD_DEC_USE_COUNT;
return 0;
}
int init_module(){
example_dir = proc_mkdir("proc_test",NULL);
example_dir->owner = THIS_MODULE;
current_file = create_proc_read_entry("current",666,example_dir,proc_read_current,NULL);
current_file->owner = THIS_MODULE;
hello_file = create_proc_entry("hello",666,example_dir);
strcpy(global_buffer,"this is a global_buffer\n");
hello_file->read_proc = proc_read_hello;
hello_file->write_proc = proc_write_hello;
hello_file->owner = THIS_MODULE;
student_file = create_proc_entry("student",666,example_dir);
student_file->read_proc = proc_read_student;
student_file->write_proc = proc_write_student;
student_file->owner = THIS_MODULE;
symlink = proc_symlink("current_symlink",example_dir,"current");
symlink->owner = THIS_MODULE;
init_student();
//proc_register(&proc_root,&proc_read_student);
//int i=0;
//for(i;i<STRINGLEN;++i){
//memset(global_buffer_student[i].name,0,NAMELEN);
//memset(global_buffer_student[i].id,0,IDLEN);
//}
printk("init_module msg form tested_proc.c\n");
return 0;
}
int proc_read_current(char* page,char** start,off_t off,int count,int *eof,void* data){
int len;
MOD_INC_USE_COUNT;
len = sprintf(page,"current process usages:\nname:%s\ngid:%d\npid:%d\n",current->comm,current->pgrp,current->pid);
MOD_DEC_USE_COUNT;
return len;
}
//void proc_write_information(){
//}
int proc_read_hello(char* page,char** start,off_t off,int count,int* eof,void* data){
int len;
MOD_INC_USE_COUNT;
len = sprintf(page,"hello message:\n %s write: %s \n",current->comm,global_buffer);
MOD_DEC_USE_COUNT;
return len;
}
int proc_write_hello(struct file *file,const char *buffer,unsigned long count,void* data){ int len;
MOD_INC_USE_COUNT;
if(count >= 1024)
len = 1024-1;
else
len = count;
copy_from_user(global_buffer,buffer,len);
global_buffer[len]='\0';
MOD_DEC_USE_COUNT;
return len;
}
void cleanup_module(){
remove_proc_entry("current_symlink",example_dir);
remove_proc_entry("hello",example_dir);
remove_proc_entry("student",example_dir);
remove_proc_entry("current",example_dir);
remove_proc_entry("proc_test",NULL);
//proc_unregister(&proc_root,proc_read_student.low_ino);
printk("cleanup_module msg form tested_proc.c\n");
}
MODULE_LICENSE("GPL");
2.示例如何使用模块
/* rwbuf: read/write a buffer
* a demo on how to build a device in a kernel module
* test pass with Mandrake 7(Kernel 2.2.14) in vmare, 2005/12
* test pass with RedHat 9(Kernel 2.4.20-8) in vmware, 2005/12
*
* how to test ?
* so :
*
* $ first you must be ROOT
compile in Kernel 2.4
* # gcc -I/usr/src/linux/include/ -D KERNEL2_4 -c rwbuf.c
compile in Kernel 2.2
* # gcc -I/usr/src/linux/include/ -c rwbuf.c
* # insmod rwbuf.o // you should see that 'rwbuf' in there
* # lsmod
* # mknod /dev/rwbuf c 60 0 // this can do only once
* # // now you can use /dev/rwbuf
*/
#define LINUX
#define __KERNEL__
#define MODULE
#define KBUILD_MODNAME rwbuf
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#ifdef KERNEL2_4
#define HAVE_MEMCPY /* no export 'memcpy' in kernel 2.2 */
#define HAVE_MOD_LIC /* no Module License in kernel 2.2 */
#endif
#ifndef HAVE_MEMCPY
#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
#endif
#define RWBUF_prefix rwbuf// not used yet
#define RWBUF_NAME "rwbuf" // device's symbol name
#define RWBUF_ID 60// device's major no
#define RW_CLEAR 0x909090 // IO ctl command
#define rwbuf_size 1000// 1k enough
static unsigned char rwbuf[rwbuf_size+1]; //
static int rwlen=0;// how many bytes used in <rwbuf>
static int inuse=0;// only one process permited at the same time
static int rwbuf_open(struct inode *inode,struct file * filep)
{
if (inuse==1)// the buf is used by another process, so fail to open
return -1;
inuse=1;
MOD_INC_USE_COUNT;// don't ask what this means
return 0;
}
static int rwbuf_close(struct inode *inode,struct file * filep)
{
inuse=0;
MOD_DEC_USE_COUNT;
return 0;
}
static ssize_t rwbuf_write(struct file * filep,
const char *buf, size_t count, loff_t * ppos)
{
if (count>rwbuf_size)
count = rwbuf_size;
#ifndef HAVE_MEMCPY /* no export 'memcpy' in kernel 2.2 */
copy_from_user(rwbuf, buf, count);
#else
memcpy(rwbuf, buf, count); // as you see
#endif
rwlen = count;
printk("user-to-kernel: %s\n", rwbuf);
return count;
}
static ssize_t rwbuf_read(struct file* filep,
char * buf, size_t count, loff_t* ppos)
{
if (count>rwlen)
count = rwlen;
#ifndef HAVE_MEMCPY /* no export 'memcpy' in kernel 2.2 */
copy_to_user(buf, rwbuf, count);
#else
memcpy(buf, rwbuf, count);
#endif
printk("kernel-to-user: %s\n", buf);
return count;
}
static int rwbuf_ioctl(struct inode *inode,struct file * filep,
unsigned int cmd,unsigned long arg)
{
switch (cmd)
{
case RW_CLEAR:
rwlen = 0;// clear buf by set its len to zero
printk("rwbuf in kernel zero-ed\n");
break;
default:
break;
};
return 0;
}
static struct file_operations rwbuf_fops =
{
open: rwbuf_open,
release: rwbuf_close,
read: rwbuf_read,
write: rwbuf_write,
ioctl: rwbuf_ioctl,
};
int init_module()
{
printk("Hello world\n");
if (register_chrdev(RWBUF_ID, RWBUF_NAME, &rwbuf_fops))
printk("register error\n");
else
printk("register ok\n");
return 0;
}
void cleanup_module()
{
if (unregister_chrdev(RWBUF_ID, RWBUF_NAME)!=0)
printk("unreg err\n");
else
printk("unreg ok\n");
printk("bye\n");
}
#ifdef HAVE_MOD_LIC
MODULE_LICENSE("GPL");
#endif
3.了解和熟悉Linux中设备驱动程序的概念和设计,能独立编写一个简单的字符型或是块型设备驱动程序
------------------------radimo.h---------------------------------------
#define RADIMO_MAJOR42
#define RADIMO_TIMER_DELAY60*HZ
/* msg masks */
#define RADIMO_OPEN1
#define RADIMO_IOCTL2
#define RADIMO_INFO4
#define RADIMO_REQUEST8
#define RADIMO_TIMER16
#define RADIMO_ERROR32
#ifndef MSG_MASK
#define MSG_MASK ( RADIMO_IOCTL | RADIMO_INFO | RADIMO_ERROR | RADIMO_REQUEST | RADIMO_OPEN)
#endif
#define MSG(mask, string, args...) \
if (MSG_MASK & mask) printk(KERN_DEBUG "radimo: " string, ##args)
------------------------radimo.c---------------------------------------
/*
* Sample Ram DIsk Module, Radimo
*
*/
#include <linux/module.h>
#if defined(CONFIG_SMP)
#define __SMP__
#endif
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include "radimo.h"
/*以上定义了一些常用的头文件*/
#define MAJOR_NRRADIMO_MAJOR// 定义了RADIMO的主设备号
#define DEVICE_NAME"radimo"// 定义了RADIMO的设备名
#define DEVICE_NR(device)(MINOR(device))
#define DEVICE_ON(device)
#define DEVICE_OFF(device)
#define DEVICE_NO_RANDOM
#include <linux/blk.h>
#define RADIMO_HARDS_BITS9/* 2**9 byte hardware sector */
#define RADIMO_BLOCK_SIZE1024/* block size */
//定义了一个块的大小,以字节为单位
#define RADIMO_TOTAL_SIZE2048/* size in blocks */
//定义了这个虚拟盘的容量,以块为单位
/* the storage pool */
static char *radimo_storage;//这个指针是全局变量,指向用于虚拟盘的内存
static int radimo_hard = 1 << RADIMO_HARDS_BITS;
static int radimo_soft = RADIMO_BLOCK_SIZE;
static int radimo_size = RADIMO_TOTAL_SIZE;
static int radimo_readahead = 4;
struct timer_list radimo_timer;
//定义了一个定时器,这个程序中我们并没有用到。这里作为一个使用定时器的例子
/* forward declarations for _fops */
static int radimo_open(struct inode *inode, struct file *file);
static int radimo_release(struct inode *inode, struct file *file);
static int radimo_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
//定义了三个常用的接口函数
static struct block_device_operations radimo_fops = {
open:radimo_open,
release:radimo_release,
ioctl:radimo_ioctl,
};
//用一个结构把三个接口函数组装起来,以便通知操作系统
static int radimo_request(request_queue_t *request_queue, int rw, struct buffer_head *sbh)
{//【重要】这是块设备驱动程序处理读写请求的函数,是本程序中最重要的部分
unsigned long offset, total;
//int *make_oops = NULL; // CR: access to this pointer will cause Oops, for debug only.
MSG(RADIMO_REQUEST, "%s sector rsector = %lu, blocknr = %lu\n",
rw == READ ? "read" : "write",
sbh->b_rsector,
sbh->b_blocknr);
//MSG宏的定义在radimo.h中,相当于printk,
//用于在log文件中打印一行,以便调试
offset = sbh->b_rsector * radimo_hard;
total = (unsigned long)sbh->b_size;
//计算需要访问的地址和大小
/* access beyond end of the device */
if (total+offset > radimo_size * (radimo_hard << 1)) {
MSG(RADIMO_REQUEST, "Error: access beyond end of the device");
/* error in request */
buffer_IO_error(sbh);
return 0;
}
//判断访问地址是否越界
MSG(RADIMO_REQUEST, "offset = %lu, total = %lu\n", offset, total);
if (rw == READ || rw==READA) {//如果是读操作,从虚拟盘的内存中复制数据到缓冲区中
memcpy(bh_kmap(sbh), radimo_storage+offset, total);
} else if (rw == WRITE) { //如果是写操作,从缓冲区中复制数据到虚拟盘的内存中
memcpy(radimo_storage+offset, bh_kmap(sbh), total);
} else {/* can't happen */
MSG(RADIMO_ERROR, "cmd == %d is invalid\n", rw);
}
/* successful */
sbh->b_end_io(sbh,1);//结束读写操作
return 0;
}
void radimo_timer_fn(unsigned long data)
{//这是用于定时器处理的函数,本程序中没有用到,但是可以作为使用定时器的框架
/* set it up again */
radimo_timer.expires = RADIMO_TIMER_DELAY + jiffies;
add_timer(&radimo_timer);
}
static int radimo_release(struct inode *inode, struct file *file)
{//关闭设备时调用
MSG(RADIMO_OPEN, "closed\n");
MOD_DEC_USE_COUNT;//减少引用计数
return 0;
}
static int radimo_open(struct inode *inode, struct file *file)
{//打开设备时调用
MSG(RADIMO_OPEN, "opened\n");
MOD_INC_USE_COUNT;//增加引用计数
/* timer function needs device to invalidate buffers. pass it as
data. */
radimo_timer.data = inode->i_rdev;
radimo_timer.expires = RADIMO_TIMER_DELAY + jiffies;
radimo_timer.function = &radimo_timer_fn;
if (!timer_pending(&radimo_timer))
add_timer(&radimo_timer);
//以上几行是设置定时器,本程序中没有用到定时器
return 0;
}
static int radimo_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{//响应一些特殊的操作,这些操作可以自己定义
unsigned int minor;
if (!inode || !inode->i_rdev)
return -EINVAL;
minor = MINOR(inode->i_rdev);
switch (cmd) {
case BLKFLSBUF: {//将缓冲写回存储区的操作
/* flush buffers */
MSG(RADIMO_IOCTL, "ioctl: BLKFLSBUF\n");
/* deny all but root */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
break;
}
case BLKGETSIZE: {//得到设备容量的操作
/* return device size */
MSG(RADIMO_IOCTL, "ioctl: BLKGETSIZE\n");
if (!arg)
return -EINVAL;
return put_user(radimo_size*2, (long *) arg);
}
case BLKRASET: {//设置设备预读值的操作
/* set read ahead value */
int tmp;
MSG(RADIMO_IOCTL, "ioctl: BLKRASET\n");
if (get_user(tmp, (long *)arg))
return -EINVAL;
if (tmp > 0xff)
return -EINVAL;
read_ahead[RADIMO_MAJOR] = tmp;
return 0;
}
case BLKRAGET: {//得到设备预读值的操作
/* return read ahead value */
MSG(RADIMO_IOCTL, "ioctl: BLKRAGET\n");
if (!arg)
return -EINVAL;
return put_user(read_ahead[RADIMO_MAJOR], (long *)arg);
}
case BLKSSZGET: {//得到设备块大小的操作
/* return block size */
MSG(RADIMO_IOCTL, "ioctl: BLKSSZGET\n");
if (!arg)
return -EINVAL;
return put_user(radimo_soft, (long *)arg);
}
default: {//其他操作
MSG(RADIMO_ERROR, "ioctl wanted %u\n", cmd);
return -ENOTTY;
}
}
return 0;
}
int init_module(void)
{//在模块被加载的时候调用
int res;
/* 块大小必须是扇区大小的整数倍 */
if (radimo_soft & ((1 << RADIMO_HARDS_BITS)-1)) {
MSG(RADIMO_ERROR, "Block size not a multiple of sector size\n");
return -EINVAL;
}
/* 分配存储空间 */
radimo_storage = (char *) vmalloc(1024*radimo_size);
if (radimo_storage == NULL) {
MSG(RADIMO_ERROR, "Not enough memory. Try a smaller size.\n");
return -ENOMEM;
}
memset(radimo_storage, 0, 1024*radimo_size);
/* 【重要】向系统注册块设备 */
res = register_blkdev(RADIMO_MAJOR, "radimo", &radimo_fops);
if (res) {
MSG(RADIMO_ERROR, "couldn't register block device\n");
return res;
}
init_timer(&radimo_timer);
/* 在系统中注册块的大小、存储容量等参数 */
hardsect_size[RADIMO_MAJOR] = &radimo_hard;
blksize_size[RADIMO_MAJOR] = &radimo_soft;
blk_size[RADIMO_MAJOR] = &radimo_size;
/* 在系统中注册响应读写请求的函数 */
blk_queue_make_request(BLK_DEFAULT_QUEUE(RADIMO_MAJOR), &radimo_request);
read_ahead[RADIMO_MAJOR] = radimo_readahead;
MSG(RADIMO_INFO, "loaded\n");
MSG(RADIMO_INFO, "sector size of %d, block size of %d, total size = %dKb\n",
radimo_hard, radimo_soft, radimo_size);
printk("init_module from radimo.c ");
return 0;
}
void cleanup_module(void)
{//在模块被卸载的时候调用
unregister_blkdev(RADIMO_MAJOR, "radimo");
del_timer(&radimo_timer);
invalidate_buffers(MKDEV(RADIMO_MAJOR,0));
/* remove our request function */
blk_dev[RADIMO_MAJOR].request_queue.request_fn = 0;
vfree(radimo_storage);
MSG(RADIMO_INFO, "unloaded\n");
printk("cleanup_module from radimo.c ");
}
MODULE_LICENSE("GPL");
------------------------Makefile---------------------------------------
# standards
INCLUDE= /usr/src/linux-2.4/include
CC = gcc
CFLAGS = -D__KERNEL__ -I$(INCLUDE) -DMODULE -Wall -O2
TARGET= radimo
SRC= radimo.c
all: $(TARGET).o
clean:
rm -f *.o *~ core
分享到:
相关推荐
STM32 V3.5库 RTT操作系统例程 STM32 HAL库 RTT操作系统例程 HC32 1.0库 RTT操作系统例程 HC32 LL库 RTT操作系统例程
uCOS-II操作系统例程
飞思卡尔dp256芯片 osek操作系统例程
例程经过测试,可以正常运行,编译器免安装,解压即可使用
STM32实时操作系统RTX5官方例程: 1、此教程由Hitex制作,以MDK的软件包形式存在。 2、提供了18个案例,每个案例都有提供教程,教程为独立PDF章节。
电子-STemwin例程带操作系统.zip,操作系统/图形界面emWin图形界面
里面包含十个对文件的操作例程,如读取文件属性,打开文件,关闭文件,删除,复制文件
包含有Freertos操作系统,方便二次开发移植。。 该例程库支持以下型号 STM32L053xx,STM32L052xx,STM32L051xx and STM32L063xx,STM32L062xx,STM32L061xx STM32L073xx,STM32L072xx,STM32L071xx and STM32L083xx,STM32L...
stm32 uGUI操作系统和ADS1256模拟采集显示曲线例程
基于Keil自带的嵌入式操作系统在STM32环境中进行验证实验
易语言数据库操作例程 酒店KTV管理系统。@易友。
易语言数据库操作例程 MV管理系统,源码涉及正则、网页访问、数据库操作。@天不老,情难绝。
教程:《51单片机C语言常用模块与综合系统设计实例精讲》,附录有一章讲RTX51的,很不错的说。 附带small-RTOS的例程,大家可以读下。个人感觉这个编程思路应用比较多。 我的笔记中有我搜集的对单个时钟长度、时间...
操作系统的定义:是一组控制和管理计算机软硬件资源,为用户提供便捷使用计算机的程序的集合。 基本功能:1.进程管理 2.存储管理 3.文件管理 4.设备管理 5.作业管理 基本组成: 1、驱动程序 最底层bai的、直接...
实验目的和要求 1. 学习LINUX系统下对文件进行操作的各种命令和图形化界面的使用方法。...2. 深入学习和掌握文件管理系统的基本原理和LINUX等操作系统下常用的系统调用,编写一个使用系统调用的例程。
STM32F103 带操作系统的例程,实现了分任务控制led,按键,串口等功能,有助于初学者学习用
s3c2440裸机例程 s3c2410裸机例程 没有操作系统,纯硬件操作
基于现在市面上最好的开发板的例程,现在最好的msp430f5438例程,很全的,有AD,液晶显示,操作系统等等,还同时附带了官方的例程,以备同时参考。