【HUST】网安|操作系统实验|实验四 设备管理、文件管理
文章目錄
- 任務(wù)
- 任務(wù)1 編寫一個Linux內(nèi)核模塊,并完成安裝/卸載等操作。
- 1. 提示
- 2. 任務(wù)代碼
- 3. 結(jié)果及說明
- 任務(wù)2 編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。
- 1. 提示
- 2. 任務(wù)代碼
- 3. 結(jié)果及說明
- 任務(wù)3 編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。
- 1. 提示
- 2. 任務(wù)代碼
- 3. 結(jié)果及說明
任務(wù)
一、實驗?zāi)康?br> 1)理解設(shè)備是文件的概念。
2)掌握Linux模塊、驅(qū)動的概念和編程流程
3)Windows /Linux下掌握文件讀寫基本操作
二、實驗內(nèi)容
1)編寫一個Linux內(nèi)核模塊,并完成安裝/卸載等操作。
2)編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。功能:write幾個整數(shù)進(jìn)去,read出其和或差或最大值。
3)編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。功能:有序讀寫內(nèi)核緩沖區(qū),返回實際讀寫字節(jié)數(shù)。
任務(wù)1 編寫一個Linux內(nèi)核模塊,并完成安裝/卸載等操作。
1. 提示
提示1:安裝時和退出時在內(nèi)核緩沖區(qū)顯示不同的字符串。
提示2:相關(guān)函數(shù):module_init( )、 module_exit( )
提示3: MODULE_LICENSE( )、 MODULE_AUTHOR ( )等可選
提示4:安裝命令:insmod XXXX.ko
提示5:擴(kuò)展:編寫帶參數(shù)的模塊程序
int mytest = 100;
module_param(mytest, int, 0644);
2. 任務(wù)代碼
先安裝一個必要的軟件包(否則會有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. 結(jié)果及說明
1)模塊作用:實驗文件編譯生成的ko模塊可接收charp型參數(shù),默認(rèn)為"shandianchengzi"。當(dāng)用戶加載模塊時輸出"Hello, dear 參數(shù)!\n",退出時輸出"GoodBye, 參數(shù)!\n"。
2)如何向模塊中傳入?yún)?shù):函數(shù)原型module_param(name, type, perm),參數(shù)name,type是自己定義的變量的類型,perm是權(quán)限。
其中常用的權(quán)限:①0755->用戶具有讀/寫/執(zhí)行權(quán)限,組用戶和其它用戶具有讀/寫權(quán)限;②0644->用戶具有讀/寫權(quán)限,組用戶和其它用戶具有只讀權(quán)限;
一般賦予目錄0755權(quán)限,而文件賦予0644權(quán)限。
3)編譯:
4)結(jié)果:
先用sudo dmesg -C清空緩沖區(qū),然后使用sudo insmod code1.ko yourID='shandianchengzi'裝入內(nèi)核并修改參數(shù)值,再dmesg顯示當(dāng)前內(nèi)容。再使用sudo rmmod code1.ko卸載內(nèi)核,再dmesg顯示當(dāng)前內(nèi)容。與預(yù)期相符。
參考:
主要:Linux中添加一個帶參數(shù)的模塊
傳入字符串的設(shè)計:第四章Linux內(nèi)核模塊之五(模塊參數(shù))
任務(wù)2 編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。
1. 提示
提示1:參考任務(wù)1
提示2:至少實現(xiàn)xx_open,xx_write,xx_read等函數(shù)
提示3:功能:
xx_write( )寫進(jìn)去2個整數(shù)
xx_read( )讀回結(jié)果(和或差或最大值)
提示4: [可選的設(shè)備注冊方式,其余方式參考baidu]
struct miscdevice mydemodrv_misc_device ;
ret = misc_register( &mydemodrv_misc_device )
2. 任務(wù)代碼
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("請輸入兩個整數(shù):");
scanf("%d%d",&a,&b);
sprintf(buffer,"%d %d",a,b);
write(fd,buffer,64);
read(fd, buffer, 64);
close(fd);
return 0;
}
3. 結(jié)果及說明
1)編譯:
2)結(jié)果:完成的是求和功能。
3)遇到的問題:最開始,打開文件指針的時候用了O_RDONLY,只讀。后來寫write的時候死活讀不進(jìn)去。。。
懷疑是中間文件沒刪、模塊代碼返回值不能size_t強(qiáng)轉(zhuǎn)ssize_t等問題,結(jié)果原來是因為這個。。。。。。。
改成O_RDWR | O_CREAT。
參考:《內(nèi)核kernel:misc機(jī)制字符設(shè)備驅(qū)動模塊編寫》
O_RDWR | O_CREAT參考:3.8 write函數(shù)-文件數(shù)據(jù)寫
4)用的方法是先讀入緩沖區(qū),再用sscanf讀。我覺得傳整型指針有點麻煩,要寫兩個write。
5)設(shè)備讀不了寫不了裝不了用不了沒輸出:
甚至把模塊卸載了,它還在!
這是因為在裝入模塊之前,不慎調(diào)用test程序,已經(jīng)提前申請打開了設(shè)備,以致于裝載的時候未裝載成功。
如果出現(xiàn)這種情況,運行:
sudo rm /dev/code2
任務(wù)3 編寫Linux驅(qū)動程序并編程應(yīng)用程序測試。
1. 提示
提示1:參考任務(wù)1
提示2:至少實現(xiàn)xx_open,xx_write,xx_read等函數(shù)
提示3:功能:
內(nèi)核分配一定長度的緩沖區(qū),比如64字節(jié)。
xx_write()寫進(jìn)去若干字符,注意維護(hù)寫入位置。下次繼續(xù)寫的話,接著該位置往后寫,直到緩沖區(qū)末尾。要返回實際寫入字?jǐn)?shù)。
xx_read()讀出若干字符串,注意維護(hù)讀出位置。下次繼續(xù)讀的話,接著該位置往后讀,直到緩沖區(qū)末尾。要返回實際讀回字?jǐn)?shù)。
擴(kuò)展:
▲緩沖區(qū)設(shè)置為循環(huán)緩沖區(qū)?
▲如何避免寫覆蓋,避免讀重復(fù)?
2. 任務(wù)代碼
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字節(jié),讀出后指針位置為%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字節(jié),寫完后緩沖區(qū)為%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("請輸入向緩沖區(qū)寫的內(nèi)容:");
scanf("%s",buffer);
write(fd,buffer,strlen(buffer));
read(fd, buffer, 64);
printf("從緩沖區(qū)讀:%s\n", buffer);
close(fd);
return 0;
}
3. 結(jié)果及說明
1)kmalloc頭文件是#include <linux/slab.h>。
2)編譯:
3)運行:
4)遇到的問題2:copy_to_user和copy_from_user的to和from參數(shù)是反過來的,一開始沒注意。
5)遇到的問題3:
下面這個不行:
if(pos - lbuf < 0)
{
lbuf = pos;
}
改成這個才行:
if(pos < lbuf)
{
lbuf = pos;
}
因為size_t是unsigned類型的,所以不能直接跟0比較。
總結(jié)
以上是生活随笔為你收集整理的【HUST】网安|操作系统实验|实验四 设备管理、文件管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vivo官网APP首页端智能业务实践
- 下一篇: Vue相关笔记