日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【HUST】网安|操作系统实验|实验四 设备管理、文件管理

發布時間:2025/5/22 编程问答 30 如意码农
生活随笔 收集整理的這篇文章主要介紹了 【HUST】网安|操作系统实验|实验四 设备管理、文件管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 任務
    • 任務1 編寫一個Linux內核模塊,并完成安裝/卸載等操作。
      • 1. 提示
      • 2. 任務代碼
      • 3. 結果及說明
    • 任務2 編寫Linux驅動程序并編程應用程序測試。
      • 1. 提示
      • 2. 任務代碼
      • 3. 結果及說明
    • 任務3 編寫Linux驅動程序并編程應用程序測試。
      • 1. 提示
      • 2. 任務代碼
      • 3. 結果及說明

任務

一、實驗目的
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】网安|操作系统实验|实验四 设备管理、文件管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。