计算机操作系统-课设 (2).doc_第1页
计算机操作系统-课设 (2).doc_第2页
计算机操作系统-课设 (2).doc_第3页
计算机操作系统-课设 (2).doc_第4页
计算机操作系统-课设 (2).doc_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

此文档收集于网络,如有侵权,请联系网站删除华中科技大学嵌入式操作系统课程设计实验报告院 系: 计算机科学与技术学院专 业: 信息安全班 级: 姓 名: 指导老师: 报告时间: 2016年3月16日计算机科学与技术学院此文档仅供学习与交流目录1程序设计目的12课程设计内容13内容一:掌握在Linux下编程环境13.1内容要求13.2实验环境13.3方案设计23.3.1 文件拷贝23.3.2 三个窗口显示进程结果23.4 调试与结果33.4.1 文件拷贝33.4.2 三个窗口显示进程结果53.5实验源代码53.5.1 文件拷贝53.4.2 三个窗口显示进程64内容二:添加系统调用104.1 内容要求104.2 实验环境104.3 方案设计104.4 调试与结果114.5 测试源代码155 内容三:添加设备驱动165.1 内容要求165.2 实验环境165.3 方案设计165.3.1知识概述165.3.2具体设计176 内容四:系统监视器246.1 内容要求246.2 实验环境246.3 方案设计246.3.1 知识概述246.3.2具体设计256.4 实验截图337 课程设计心得体会601程序设计目的1) 掌握Linux操作系统的使用方法;2) 了解Linux系统内核代码结构;3) 掌握实例操作系统的实现方法。2课程设计内容1) 掌握Linux操作系统的使用方法,包括键盘命令、系统调用;掌握在Linux下的编程环境。掌握系统调用的实现过程,通过编译内核方法,增加一个新的系统调用。另编写一个应用程序,使用新增加的系统调用。2) 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,其功能可以简单。3) 使用GTK/QT实现系统监控器。3内容一:掌握在Linux下编程环境3.1内容要求1) 编一个C程序,其内容为实现文件拷贝的功能(使用系统调用open/read/write.);2) 编一个C程序,其内容为分窗口同时显示三个并发进程的运行结果。要求用到Linux下的图形库。 (gtk/Qt)3.2实验环境操作系统:14.04.1-Ubuntu编译器:GCC3.3方案设计3.3.1 文件拷贝 Linux 文件操作系统调用的常用函数有 open、read、write,通过这三个系统调用函数就可以实现文件的拷贝。函数原型如下: int open(const char *pathname, int flag); ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void* buf, size_t count); 首先用只读模式打开源文件,即 flag=O_RDONLY,然后用 open 函数创建目标文件,flag=O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR。用 read 函数每次从源文件读取 1024 字节的数据,然后用 write 函数每次写入 1024 字节到目标文件,直到读取完毕。3.3.2 三个窗口显示进程结果 本次实验使用的图形库是跨平台的开发工具Qt。首先下载Qt的安装包并安装。 Qt安装完之后,先新建一个Qt控制台应用MAIN作为主进程,用于调用三个并发的子进程。在主进程的main函数中,使用fork创建三个子进程,若进程创建成功(即fork函数返回值等于0),则使用execv函数进入对应的子进程(get、copy、put)。 主进程程序编写完成后,再新建三个Qt Widgets Application,分别作为三个子进程get、copy、put(所实现的功能并不是拷贝)。由于三个子进程窗口显示的内容形式一模一样,所以以子进程get为例。get进程的窗口显示了一下四个内容:当前时间、子进程名称、子进程的pid和父进程MAIN的pid。用Qt的对象QDateTime获取系统当前时间,然后将时间转换成一个字符串写在一个QLabel类的实例中,然后将该实例添加至窗口;直接把当前进程名称写在一个标签上然后添加至窗口;使用getpid和getppid函数分别获取当前进程号和父进程号,然后调用sprintf把进程号转换成字符串类型之后写在标签上并添加至窗口即可。3.4 调试与结果3.4.1 文件拷贝将1.txt中的内容拷贝给2.txt,拷贝前如下:编译好测试程序之后,输入如下图所示命令行:打开文件1.txt以及2.txt查看实验结果,如下图所示:3.4.2 三个窗口显示进程结果 主进程和三个子进程的程序全部编写完后,直接在Qt上编译运行。程序运行结果如下所示:3.5实验源代码3.5.1 文件拷贝#include #include #include #include #include #define SIZE 1024 int main(int argc,char *argv) int file1_fd,file2_fd; /文件描述符 int num_read,num_write; char bufferSIZE; if(argc!=3) fprintf(stderr,The format of command must be %s filename1 filename2n,argv0); exit(1); /*打开源文件*/ if(file1_fd=open(argv1,O_RDONLY)=-1) fprintf(stderr,%s open error:%sn,argv1,strerror(errno); exit(1); /*创建目标文件*/ if(file2_fd=open(argv2,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR)=-1) fprintf(stderr,%s open error:%sn,argv2,strerror(errno); exit(1); /*实现文件拷贝*/ while(num_read=read(file1_fd,buffer,sizeof(buffer)0) num_write=write(file2_fd,buffer,num_read); close(file1_fd); close(file2_fd); exit(0); 3.4.2 三个窗口显示进程主进程#include mainwindow.h#include #include #include #include #include #include int main(int argc, char *argv) QApplication a(argc, argv); pid_t p1,p2,p3; if(p1 = fork() = 0) execv(/home/liuxvzhe/Documents/Untitled Folder/Process_A,NULL); else if(p2 = fork() = 0) execv(/home/liuxvzhe/Documents/Untitled Folder/Process_B,NULL); else if(p3 = fork() = 0) execv(/home/liuxvzhe/Documents/Untitled Folder/Process_C,NULL); waitpid(p1,NULL,0); waitpid(p2,NULL,0); waitpid(p3,NULL,0); MainWindow w; w.show(); return a.exec();子进程1#include mainwindow.h#include ui_mainwindow.h#include #include #include #include MainWindow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui:MainWindow),sharememory1(share1) ui-setupUi(this); setWindowTitle(get); setWindowFlags(Qt:Dialog); move(0,0); resize(500,500); char str128,f_id128; sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textBrowser-setText(get); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate(); timer-start(1);MainWindow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);子进程2#include mainwindow.h#include ui_mainwindow.h#include #include #include #include MainWindow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui:MainWindow),sharememory1(share1),sharememory2(share2) char str128,f_id128; ui-setupUi(this); setWindowTitle(copy); setWindowFlags(Qt:Dialog); move(500,500); resize(500,500); sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textBrowser-setText(copy); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate(); timer-start(1);MainWindow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);子进程3#include mainwindow.h#include ui_mainwindow.h#include #include #include #include MainWindow:MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui:MainWindow),sharememory2(share2) char str128,f_id128; ui-setupUi(this); setWindowTitle(put); setWindowFlags(Qt:Dialog); move(1000,0); resize(500,500); sprintf(str,%d,getpid(); sprintf(f_id,%d,getppid(); ui-textBrowser-setText(put); ui-textBrowser_2-setText(str); ui-textBrowser_3-setText(f_id); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout(), this, SLOT(timerUpDate(); timer-start(1);MainWindow:MainWindow() delete ui;void MainWindow:timerUpDate() QDateTime time = QDateTime:currentDateTime(); QString str = time.toString(yyyy-MM-dd hh:mm:ss dddd); ui-labelCurDate-setText(str);4内容二:添加系统调用4.1 内容要求1) 内核编译、生成,用新内核启动;2) 新增系统调用实现:文件拷贝或P、V操作。4.2 实验环境操作系统:14.04.1-Ubuntu编译器:GCC4.3 方案设计 本次课程设计添加了一个文件拷贝的系统调用。在内核下打开读写所用到的函数有:sys_open,sys_read,sys_write。函数体与前面的用系统调用实现文件拷贝相同,代码如下: asmlinkage int sys_mycall(char* fromFile,char* toFile) int SIZE = 1024; int from,to,count; char bufferSIZE; mm_segment_t fs; /段操作的初始化 fs = get_fs(); set_fs(get_ds(); /* 系统调用打开源文件,若失败,返回-1 */ if(from = sys_open(fromFile,O_RDONLY,S_IRUSR) = -1) printk(Error in oen source file!); return -1; /* 系统调用创建并打开目标文件,若失败,返回-2 */ if(to = sys_open(toFile,O_RDWR | O_CREAT | O_TRUNC,S_IRUSR | S_IWUSR) = -1) printk(Error in open target file!); return -2; while(count=sys_read(from,buffer,SIZE) /* 拷贝文件,若失败,返回-3 */ if (count = -1 | sys_write(to,buffer,count) = -1) printk(Error in copy file!); return -3; sys_close(from); sys_close(to); set_fs(fs); /段操作结束 return 0; 4.4 调试与结果1) 下载并解压内核 到官方网站 /下载内核 linux-3.18.27,直接解压到下载内核存放的路径下。2) 修改内核 第 一 步 修 改 系 统 调 用 模 块 的 源 码 , 在 root 权 限 下 打 开/home/liuxvzhe/Downloads/linux-3.18.27/kernel/sys.c,在文件的末尾添加 asmlinkage int sys_mycall(char* fromFile,char* toFile)函数体。然后添加声明到头文件,修改文件/include/linux/syscalls.h。最后添加系统调用号,在/home/liuxvzhe/Downloads/linux-3.18.27/arch/x86/syscalls/syscall_64.tbl下,我们只要找一没被使用的系统调用号,用该号给我们自定义函数使用,比如:#define _NR_sys_mycall 337,定义系统调用 sys_mycall 的系统调用号为 337。3) 净化并配置新内核sudo make mrproper 净化解压后的源代码; sudo make menuconfig 对内核选项进行配置; 如果这一步有错误可能是正在使用的系统没有安装必要的库文件,如 ncurses、libncurses*,这时候需要输入如下指令来安装: 首先回到系统根目录 sudo apt-get install ncurses sudo apt-get install libncurses* 依照提示就能安装好必要的库文件了。然后再回到内核源码的目录下尝试使用sudo make menuconfig 对内核选项进行配置。 sudo make dep 建立模块间的依赖信息4) 编译内核sudo make bzImage 编译内核 sudo make modules 编译内核模块 5) 更新启动项文件update-grub2 6) 修改/boot/grub/ 目录下 grub.cfg 文件 进入文件之后,按 Ctrl+F 查找 timeout ,将所有的 timeout 数值改为 10;这个数值的单位是秒,这么做的目的是修改启动项的暂停时间,以便让用户有足够的时间选择要进入的操作系统。7) 重启系统,启动项如图所示;8) 选取新内核,进行测试;4.5 测试源代码#include #include #include int main(int argc,char* argv) int i; if(argc!=3) printf(Error in command!); return 0; i = syscall(322,argv1,argv2);/337 是系统调用号 printf(i = %dn,i); printf(Copy file successful!n); return 1; 5 内容三:添加设备驱动5.1 内容要求 掌握增加设备驱动程序的方法。通过模块方法,增加一个新的设备驱动程序,实现简单的功能。5.2 实验环境操作系统:14.04.1-Ubuntu编译器:GCC5.3 方案设计5.3.1知识概述 Linux核心是一种monolithic类型的内核,即单一的大核心,另外一种形式是MicroKernel,核心的所有功能部件都被拆成独立部分, 这些部分之间通过严格的通讯机制进行联系。Linux内核是一个整体结构,因此向内核添加任何东西.或者删除某些功能,都十分困难 。为了解决这个问题,引入了模块机制,从而可以动态的在内核中添加或者删除模块。模块一旦被插入内核,就和内核其他部分一样。 Linux内核中的设备驱动程序是一组常驻内存的具有特权的共享库,是低级硬件处理例程。对用户程序而言,设备驱动程序隐藏了设备的具体细节, 对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文 件,用户程序可以像对其它文件一样对此设备文件进行操作。Linux支持3种设备:字符设备、块设备和网络设备。设备由一个主设备号和一个次设备号标识。主设备号唯一标识了设备类型, 即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释 ,一般用于识别在若干可能的硬件设备中,I/O请求所涉及到的那个设备。典型的Linux模块实现机制有如下几步: 注册设备:在系统初启或者加载模块的时候,必须将设备登记到相应的设备数组,并返回主设备号。 定义功能函数:对于每一个驱动函数来说,都有一些和此设备密切相关的功能函数。以最常用的块设备或者字符设备来说,都存在着诸如 open()、read()这一类的操作。当系统调用这些调用时,将自动的使用驱动函数中特定的模块来实现具体的操作。卸载设备:在不用这个设备时,可以将它卸载,主要是从/proc 中取消这个设备的特殊文件。5.3.2具体设计1) 编写Makefile文件Makefile文件用于编译设备驱动程序,具体内容如下:ifneq ($(KERNELRELEASE),) obj-m := Mydevice.oelsePWD :=$(shell pwd)KVER :=$(shell uname -r)KDIR :=/lib/modules/$(KVER)/buildall:$(MAKE) -C $(KDIR) M=$(PWD)clean:#rm -f *.cmd *.o *.mod *.korm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions#$(MAKE) -C $(KDIR) M=$(PWD) cleanendif2) 编写设备功能函数编写设备驱动程序的主要工作就是编写子功能函数,并填充file_operations的各个域 。结构体file_operations的具体定义如下:struct file_operations struct module *owner;/拥有该结构的模块的指针,一般为THIS_MODULES loff_t (*llseek) (struct file *, loff_t, int);/用来修改文件当前的读写位置 ssize_t (*read) (struct file *, char _user *, size_t, loff_t *);/从设备中同步读取数据 ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *);/向设备发送数据ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/初始化一个异步的读取操作 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/初始化一个异步的写入操作 int (*readdir) (struct file *, void *, filldir_t);/仅用于读取目录,对于设备文件,该字段为NULL unsigned int (*poll) (struct file *, struct poll_table_struct *); /轮询函数,判断目前是否可以进行非阻塞的读写或写入 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); /执行设备I/O控制命令 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); /不使用BLK文件系统,将使用此种函数指针代替ioctl long (*compat_ioctl) (struct file *, unsigned int, unsigned long); /在64位系统上,32位的ioctl调用将使用此函数指针代替 int (*mmap) (struct file *, struct vm_area_struct *); /用于请求将设备内存映射到进程地址空间 int (*open) (struct inode *, struct file *); /打开 int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); /关闭 int (*fsync) (struct file *, struct dentry *, int datasync); /刷新待处理的数据 int (*aio_fsync) (struct kiocb *, int datasync); /异步刷新待处理的数据 int (*fasync) (int, struct file *, int); /通知设备FASYNC标志发生变化 int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock *); ;子功能函数详细代码见Error! Reference source not found.。3) 安装设备驱动程序1 make clean,清除make产生的残留2 make,重新调用Makefile编译设备驱动程序3 insmod -f MyDeviceDriver.ko,加载生成的 MyDeviceDriver.ko模块4 cat /proc/devices,获取设备驱动程序的主设备号5 mknod /dev/MyDeviceDriver c 250 0;,创建设备文件,250为主设备号,0为从设备号4) 测试驱动程序 此设备驱动程序实现的功能是将一个字符串中内容拷贝到另外一个字符串中。测试程序编写完成后,在终端输入gcc Testdev.c -o Testdev进行编译。测试结果如下:5.4源代码1) 设备驱动程序Mydevice.c#include #include #include #include #include #include #include unsigned int major = 0;/ 主设备号 static int mutex = 0; static char buffer1024=Mydevice; static ssize_t read_test(struct file *file, char _user *user, size_t t, loff_t *f); static ssize_t write_test(struct file *file, const char _user *user, size_t t, loff_t *f); static int open_test(struct inode *inode,struct file *file); static int release_test(struct inode *inode,struct file *file); struct file_operations test_fops= .read = read_test, .write = write_test, .open = open_test, .release = release_test,; /*注册模块*/ int init_module(void) int dev; /* 函数中第一个参数是告诉系统,新注册的设备的主设备号由系统分配, * 第二个参数是新设备注册时的设备名字, * 第三个参数是指向 file_operations 的指针, * 当用设备号为 0 创建时,系统一个可以用的设备号创建模块 */ dev = register_chrdev(0,Mydevice,&test_fops); if( dev0) printk(Regist failure!n); return dev; else printk(The device has been registered!n); major = dev; printk(The virtual devices major number: %d.n, major); return 0; /*注销模块*/ void cleanup_module(void) unregister_chrdev(major,Mydevice); printk(unregister it success!n); static ssize_t read_test(struct file *file, char _user *user, size_t t, loff_t *f) /*copy_to_user *作用:从内核区中读取数据到用户区, *如果数据拷贝成功,则返回零;否则,返回没有拷贝成功的数据字节数*/ if(copy_to_user(user,buffer,sizeof(buffer) return -EFAULT; /返回一个错误代码 return sizeof(buffer); static ssize_t write_test(struct file *file, const char _user *user, size_t t, loff_t *f) if(copy_from_user(buffer,user,sizeof(buffer)/将用户区中的数据拷贝到内核区 return -EFAULT; return sizeof(buffer); static int open_test(struct inode *inode,struct file *file) if (mutex) return -EBUSY; mutex = 1; printk(Mydevice is called!n); try_module_get(THIS_MODULE); return 0; static int release_test(struct inode *inode,struct file *file) printk(Device released!n); return 0; 2) 驱动程序测试程序Testdev.c#include #include #include #include #include int main(void) int mydev; char buf1024; char get1024; mydev = open(/dev/Mydevice,O_RDWR); /O_RDONLY,O_RDWR if(mydev=-1) printf(MYdevice open failedn); return -1; printf(read: %sn, buf); printf(Please input the data you want to test:n); scanf(%s,get); write(mydev,get,sizeof(get); lseek(mydev,0,SEEK_SET); read(mydev,buf,sizeof(get); printf(write: %sn,buf); return 0; 6 内容四:系统监视器6.1 内容要求使用GTK/QT实现系统监控器1)了解/proc文件的特点和使用方法;2)监控系统状态,显示系统中若干部件使用情况;3)用图形界面实现系统监控状态。6.2 实验环境操作系统:14.04.1-Ubuntu开发环境:Qt 方案设计6.3.1 知识概述1) proc文件系统的特点Linux的PROC文件系统是进程文件系统和内核文件系统的组成的复合体,是将内核数据对象化为文件形式进行存取的一种内存文件系统,是监控内核的一种用户接口。它拥有一些特殊的文件(纯文本),从中可以获取系统状态信息。2) /proc/cpuinfo保存CPU信息,包括名称、型号、数目、主频、Cache等;3) /proc/version保存操作系统信息,包括系统版本、内核型号、GCC版本等;4) /proc/stat保存CPU活动信息数据,用来测算CPU使用率;5) /proc/meminfo保存内存空间和交换空间实时大小,可用来计算内存和交换分区使用率,MemTotal表示内存空间总大小,MemFree表示内存剩余空间大小,SwapTotal表示交换分区总大小,SwapFree表示交换分区剩余空间大小。据此可以算出内存和交换分区的使用率。6.3.2具体设计1)功能清单1 获取并显示主机名,与之相关的proc文件为/proc/sys/kernel/hostname;2 获取并显示系统启动的时间,与之相关的proc文件为/proc/uptime;3 系统到目前为止持续运行的时间,与之相关的proc文件为/proc/uptime;4 显示系统的版本号,与之相关的proc文件为/proc/sys/kernel/ostype和/proc/sys/kernel/osrelease;5 显示CPU的型号和主频大小,与之相关的proc文件为/proc/cpuinfo;6 通过pid或者进程名查询一个进程,并显示该进程的详细信息,提供杀掉该进程的功能,与之相关的proc文件为/proc/(pid)/stat;7 显示系统所有进程的一些信息,包括pid、ppid、占用内存大小、优先级等,与之相关的proc文件为/proc/(pid)/stat, /proc/(pid)/statm;8 CPU使用率的图形化显示(2分钟内的历史记录曲线),与之相关的proc文件为/proc/stat;9 内存和交换分区的使用率的图形化显示(2分钟内的历史曲线),与之有关的proc文件为/proc/meminfo;10 在状态栏显示当前时间,未使用到/proc中的文件;11 在状态栏显示当前CPU使用率,与之相关的proc文件为/proc/stat;12 在状态栏显示当前内存使用情况,与之相关的proc文件为/proc/meminfo;13 用新线程运行一个其他程序,未使用到/proc中的文件;14 关机功能,未使用到/proc中的文件;2) 功能实现获取并显示主机名 用fopen函数打开/proc/sys/kernel/hostname文件,然后以文件指针为输入流,用fgets从其中读出一行字符包含主机名,然后用格式化输出函数sscanf函数输出一个字符串,即主机名。获取并显示系统启动的时间 从文件/proc/uptime中获取系统启动到现在的运行时间(单位是s),然后调用time函数获取系统当前时间(单位是s),用当前时间秒数减去运行时间秒数即为系统启动的时间秒数,然后调用localtime函数将系统启动时间秒数转换成tm结构体类型

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论