【HUST】网安|操作系统实验|实验四 设备管理、文件管理
文章目录
任务
一、实验目的
1)理解设备是文件的概念。
2)掌握Linux模块、驱动的概念和编程流程
3)Windows /Linux下掌握文件读写基本操作
二、实验内容
1)编写一个Linux内核模块,并完成安装/卸载等操作。
2)编写Linux驱动程序并编程应用程序测试。功能:write几个整数进去,read出其和或差或最大值。
3)编写Linux驱动程序并编程应用程序测试。功能:有序读写内核缓冲区,返回实际读写字节数。
任务1 编写一个Linux内核模块,并完成安装/卸载等操作。
1. 提示
提示1:安装时和退出时在内核缓冲区显示不同的字符串。
提示2:相关函数:module_init( )、 module_exit( )
提示3: MODULE_LICENSE( )、 MODULE_AUTHOR ( )等可选
提示4:安装命令:insmod XXXX.ko
提示5:扩展:编写带参数的模块程序
int mytest = 100;
module_param(mytest, int, 0644);
2. 任务代码
先安装一个必要的软件包(否则会有warning):
sudo apt install libelf-dev
文件code1.c:
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
#include<linux/sched.h>
MODULE_LICENSE("GPL");
static char* yourID="shandianchengzi";
module_param(yourID,charp,0644);
static int code1_init(void){
//输出欢迎信息
printk(KERN_ALERT"Hello, dear %s!\n", yourID);
return 0;
}
static void code1_exit(void){
printk(KERN_ALERT"Goodbye, %s!\n", yourID);
}
module_init(code1_init);
module_exit(code1_exit);
Makefile:
obj-m += code1.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
然后运行:
sudo make
3. 结果及说明
1)模块作用:实验文件编译生成的ko模块可接收charp型参数,默认为"shandianchengzi"。当用户加载模块时输出"Hello, dear 参数!\n",退出时输出"GoodBye, 参数!\n"。
2)如何向模块中传入参数:函数原型module_param(name, type, perm)
,参数name,type是自己定义的变量的类型,perm是权限。
其中常用的权限:①0755->用户具有读/写/执行权限,组用户和其它用户具有读/写权限;②0644->用户具有读/写权限,组用户和其它用户具有只读权限;
一般赋予目录0755权限,而文件赋予0644权限。
3)编译:
4)结果:
先用sudo dmesg -C
清空缓冲区,然后使用sudo insmod code1.ko yourID='shandianchengzi'
装入内核并修改参数值,再dmesg
显示当前内容。再使用sudo rmmod code1.ko
卸载内核,再dmesg
显示当前内容。与预期相符。
参考:
主要:Linux中添加一个带参数的模块
传入字符串的设计:第四章Linux内核模块之五(模块参数)
任务2 编写Linux驱动程序并编程应用程序测试。
1. 提示
提示1:参考任务1
提示2:至少实现xx_open,xx_write,xx_read等函数
提示3:功能:
xx_write( )写进去2个整数
xx_read( )读回结果(和或差或最大值)
提示4: [可选的设备注册方式,其余方式参考baidu]
struct miscdevice mydemodrv_misc_device ;
ret = misc_register( &mydemodrv_misc_device )
2. 任务代码
code2.c:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#define NAME "code2"
MODULE_LICENSE("GPL");
static struct device *mydemodrv_device;
static int a=0,b=0;
static int demodrv_open(struct inode *inode, struct file *file)
{
int major = MAJOR(inode->i_rdev);
int minor = MINOR(inode->i_rdev);
printk("%s: major=%d, minor=%d\n", __func__, major, minor);
return 0;
}
static int demodrv_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t
demodrv_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{
printk("%s: a+b=%d\n", __func__,a+b);
return 0;
}
static ssize_t
demodrv_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
if(count>64)
{
count = 64;
}
char temp[64];
if(copy_from_user(temp,buf,count))
{
return -EFAULT;
}
sscanf(temp, "%d%d",&a,&b);
printk("%s: a=%d,b=%d\n", __func__,a,b);
return count;
}
static const struct file_operations demodrv_fops = {
.owner = THIS_MODULE,
.open = demodrv_open,
.release = demodrv_release,
.read = demodrv_read,
.write = demodrv_write
};
static struct miscdevice mydemodrv_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = NAME,
.fops = &demodrv_fops,
};
static int __init code2_init(void)
{
int ret;
ret = misc_register(&mydemodrv_misc_device);
if (ret) {
printk("failed register code2 misc device\n");
return ret;
}
mydemodrv_device = mydemodrv_misc_device.this_device;
printk("succeeded register char device: %s\n", NAME);
return 0;
}
static void __exit code2_exit(void)
{
printk("removing device: %s\n", NAME);
misc_deregister(&mydemodrv_misc_device);
}
module_init(code2_init);
module_exit(code2_exit);
测试程序:
test.c:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define DEV_NAME "/dev/code2"
int main()
{
char buffer[64];
int fd,a,b;
fd = open(DEV_NAME, O_RDWR | O_CREAT);
if (fd < 0) {
printf("open device %s failded\n", DEV_NAME);
return -1;
}
printf("请输入两个整数:");
scanf("%d%d",&a,&b);
sprintf(buffer,"%d %d",a,b);
write(fd,buffer,64);
read(fd, buffer, 64);
close(fd);
return 0;
}
3. 结果及说明
1)编译:
2)结果:完成的是求和功能。
3)遇到的问题:最开始,打开文件指针的时候用了O_RDONLY,只读。后来写write的时候死活读不进去。。。
怀疑是中间文件没删、模块代码返回值不能size_t强转ssize_t等问题,结果原来是因为这个。。。。。。。
改成O_RDWR | O_CREAT。
参考:《内核kernel:misc机制字符设备驱动模块编写》
O_RDWR | O_CREAT参考:3.8 write函数-文件数据写
4)用的方法是先读入缓冲区,再用sscanf读。我觉得传整型指针有点麻烦,要写两个write。
5)设备读不了写不了装不了用不了没输出:
甚至把模块卸载了,它还在!
这是因为在装入模块之前,不慎调用test程序,已经提前申请打开了设备,以致于装载的时候未装载成功。
如果出现这种情况,运行:
sudo rm /dev/code2
任务3 编写Linux驱动程序并编程应用程序测试。
1. 提示
提示1:参考任务1
提示2:至少实现xx_open,xx_write,xx_read等函数
提示3:功能:
内核分配一定长度的缓冲区,比如64字节。
xx_write()写进去若干字符,注意维护写入位置。下次继续写的话,接着该位置往后写,直到缓冲区末尾。要返回实际写入字数。
xx_read()读出若干字符串,注意维护读出位置。下次继续读的话,接着该位置往后读,直到缓冲区末尾。要返回实际读回字数。
扩展:
▲缓冲区设置为循环缓冲区?
▲如何避免写覆盖,避免读重复?
2. 任务代码
code3.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/slab.h> /*kmalloc*/
#define NAME "code3"
MODULE_LICENSE("GPL");
static struct device *mydemodrv_device;
static char *device_buffer;
static size_t pos;
#define MAX_DEVICE_BUFFER_SIZE 64
static int demodrv_open(struct inode *inode, struct file *file)
{
device_buffer = kmalloc(MAX_DEVICE_BUFFER_SIZE, GFP_KERNEL);
pos=0;
return 0;
}
static ssize_t
demodrv_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos)
{
if(pos < lbuf)
{
lbuf = pos;
}
if(copy_to_user(buf,device_buffer+pos-lbuf,lbuf))
{
return -EFAULT;
}
pos=pos-lbuf;
printk("%s: 读出%ld字节,读出后指针位置为%ld\n", __func__, lbuf, pos);
return lbuf;
}
static ssize_t
demodrv_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
if(pos + count > 64)
{
count = 64-pos;
if(count < 0)
return count;
}
if(copy_from_user(device_buffer+pos,buf,count))
{
return -EFAULT;
}
pos=pos+count;
printk("%s: 写入%ld字节,写完后缓冲区为%s\n", __func__, count, device_buffer);
return count;
}
static const struct file_operations demodrv_fops = {
.owner = THIS_MODULE,
.open = demodrv_open,
.read = demodrv_read,
.write = demodrv_write
};
static struct miscdevice mydemodrv_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = NAME,
.fops = &demodrv_fops,
};
static int __init code3_init(void)
{
int ret;
ret = misc_register(&mydemodrv_misc_device);
if (ret) {
printk("failed register code2 misc device\n");
return ret;
}
mydemodrv_device = mydemodrv_misc_device.this_device;
printk("succeeded register char device: %s\n", NAME);
return 0;
}
static void __exit code3_exit(void)
{
kfree(device_buffer);
printk("removing device: %s\n", NAME);
misc_deregister(&mydemodrv_misc_device);
}
module_init(code3_init);
module_exit(code3_exit);
测试程序:
test.c:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define DEV_NAME "/dev/code3"
int main()
{
char buffer[64];
int fd,a,b;
fd = open(DEV_NAME, O_RDWR | O_CREAT);
if (fd < 0) {
printf("open device %s failded\n", DEV_NAME);
return -1;
}
printf("请输入向缓冲区写的内容:");
scanf("%s",buffer);
write(fd,buffer,strlen(buffer));
read(fd, buffer, 64);
printf("从缓冲区读:%s\n", buffer);
close(fd);
return 0;
}
3. 结果及说明
1)kmalloc头文件是#include <linux/slab.h>。
2)编译:
3)运行:
4)遇到的问题2:copy_to_user和copy_from_user的to和from参数是反过来的,一开始没注意。
5)遇到的问题3:
下面这个不行:
if(pos - lbuf < 0)
{
lbuf = pos;
}
改成这个才行:
if(pos < lbuf)
{
lbuf = pos;
}
因为size_t
是unsigned类型的,所以不能直接跟0比较。
【HUST】网安|操作系统实验|实验四 设备管理、文件管理的更多相关文章
- 201671030113 李星宇 实验十四 团队项目评审&课程学习总结
项目 内容 所属课程 [所属课程(https://www.cnblogs.com/nwnu-daizh/) 作业要求 作业要求 课程学习目标 (1)掌握软件项目评审会流程:(2)反思总结课程学习内容 ...
- 20145221 《Java程序设计》实验报告四:Android开发基础
20145221 <Java程序设计>实验报告四:Android开发基础 实验要求 基于Android Studio开发简单的Android应用并部署测试; 了解Android组件.布局管 ...
- 201671010426 孙锦喆 实验十四 团队项目评审&课程学习总结
徐明锦 徐明锦 2 95 2019-06-30T14:54:00Z 2019-06-30T14:54:00Z 9 608 3472 28 8 4072 14.00 Clean Clean false ...
- 201671010446姚良实验十四团队项目评审&课程总结
实验十四 团队项目评审&课程学习总结 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...
- 201671030114 马秀丽 实验十四 团队项目评审&课程学习总结
项目 内容 作业所属课程 所属课程 作业要求 作业要求 课程学习目标 (1)掌握软件项目评审会流程:(2)反思总结课程学习内容 任务一:团队项目审核已完成.项目验收过程意见表已上交. 任务二:课程学习 ...
- 201671030106 何启芝 实验十四 团队项目评审&课程学习总结
项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十四 团队项目评审&课程学习总结 课程学习目 ...
- 201671030111 李蓉 实验十四 团队项目评审&课程学习总结
项目 内容 这个作业属于哪个课程 软件工程 这个作业的要求在哪里 实验十四 团队项目评审&课程学习总结 作业学习目标 掌握软件项目评审会流程,反思总结课程学习内容. 任务一:结合本学期课程学习 ...
- 实验十四 第九组 张燕~杨蓉庆~杨玲 Swing图形界面组件
实验十四 Swing图形界面组件 8-11-29 理论知识 Swing和MVC设计模式 (1)设计模式(Design pattern)是设计者一种流行的 思考设计问题的方法,是一套被反复使用,多数人 ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十四:储存模块
实验十四比起动手笔者更加注重原理,因为实验十四要讨论的东西,不是其它而是低级建模II之一的模块类,即储存模块.接触顺序语言之际,“储存”不禁让人联想到变量或者数组,结果它们好比数据的暂存空间. . i ...
- 20145203Java实验报告四:Android开发基础
Java实验报告四:Android开发基础 实验要求: 1.安装Android Studio 2.运行安卓AVD模拟器 3.使用安卓运行出虚拟手机并显示HelloWorld以及自己的学号 实验过程 ( ...
随机推荐
- BurpSuite重放发包的一些区别
目录 Send Group in parallel Single connection 和 Separate connections 的差别 实际应用场景 Reference 2022年之后,Burp ...
- 2分钟学会 DeepSeek API,竟然比官方更好用!
大家好,我是程序员鱼皮.最近 DeepSeek AI 太火了,效果也很强,但致命问题是 不稳定, 经常给我返回 服务器繁忙,请稍后再试,甚至让我怀疑自己被杀熟了. 也有网友说,第一次使用成功率很高,第 ...
- C++最基本调用动态链接库dll方法的小结
针对当时初学动态链接.静态链接,有些文档整理一下发出来算是给自己和读者一个小结. 首先创建DLL 编辑头文件 dllmain.h 头文件: #pragma once #if defined(_DLL_ ...
- FastAPI极速入门:15分钟搭建你的首个智能API(附自动文档生成)🚀
title: FastAPI极速入门:15分钟搭建你的首个智能API(附自动文档生成) date: 2025/3/1 updated: 2025/3/1 author: cmdragon excerp ...
- 基于正则化的图自编码器在推荐算法中的应用 Application of graph auto-encoders based on regularization in recommendation algorithms
引言 看过的每一篇文章,都是对自己的提高.不积跬步无以至千里,不积小流无以成江海,积少成多,做更好的自己. 本文基于2023年4月6日发表于SCIPEERJ COMPUTER SCIENCE(PEER ...
- MySQL错误码大全
B.1. 服务器错误代码和消息服务器错误信息来自下述源文件:· 错误消息信息列在share/errmsg.txt文件中."%d"和"%s"分别代表编号和字符串, ...
- 1、从DeepSeek API调用到Semantic Kernel集成:深度解析聊天机器人开发全链路
引言:AI时代下的聊天机器人开发范式演进 在生成式AI技术爆发的当下,基于大语言模型(LLM)的聊天机器人开发已形成标准化技术链路.本文将结合DeepSeek API与微软Semantic Kerne ...
- 工作面试必备:SQL 中的各种连接 JOIN 的区别总结!
前言 尽管大多数开发者在日常工作中经常用到Join操作,如Inner Join.Left Join.Right Join等,但在面对特定查询需求时,选择哪种Join类型以及如何使用On和Where子句 ...
- linux重启后,启动docker和docker对应的服务
我的项目部署在docker上,linux关闭之后,项目要重启,在此做一个记录1.启动linux之后,执行docker images或者docker ps,如果出现下面的错误Cannot connect ...
- Redis 原理 - Hash
Hash 数据结构 使用 ziplist 当同时满足下面两个条件时,使用 ziplist 存储数据 元素个数少于512个 (hash-max-ziplist-entries: 512) 每个元素长度小 ...