版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、北京联合大学 信息 学院实 验 报 告题目: 操作系统实验 系 别: 计算机科学与技术 专 业: 计算机科学与技术 班 级: 计算机1303B 学 号: 2013080332058 姓 名: 刘佳敏 指导教师: 孙悦 2015年11月 19日实验二 进入VI编辑器格式:vi 文件名例 :vi sy.cVi编辑器三种工作方式:1 编辑方式:进入VI 处于编辑方式2 文本输入方式:在编辑方式下输入a ,进入追加方式,输入i,进入插入方式3 命令方式:在输入方式下,按Esc 键,由文本输入转向编辑方式,输入冒号:进入命令方式4 退出vi : wq写文件退出:w wenjianming 写文件: q!
2、 不写退出:wq! 写退出编译c文件Gcc -o wenjianming.out wenjianming.c运行文件:./wenjianming.out1 实验内容和目的用vi编辑器编辑下列文件,使用gcc编译器和gdb调试器,对下列程序编译运行,分析运行结果。要求至少完成3个程序。2程序示例(1) /* 父子进程之间的同步之例 */#include <stdio.h> main( ) int pid1; /*声明*/if(pid1=fork() /*调用fork函数复制创建child1进程*/ if (fork() /*调用fork函数复制child1进程创建child2进程,即
3、child1的子进程*/ printf (“parents context.n”); printf(“parent is waiting the child1 terminate.n); wait(0); /*父进程同步等待子进程结束,结束之后进行下一步,否则继续等待*/ printf(“parent is waiting the child2 terminate.n”);wait(0); /*父进程同步等待子进程结束,结束之后进行下一步,否则继续等待*/ printf(“parent terminate.n”);exit(0); /*父进程终止*/ Else /*如果创建child2进程不成
4、功,进行以下操作*/ /* child2*/ printf(“child2s context.n”); sleep(5); /*休眠5秒钟*/ printf(“ child2 terminate.n”); exit(0); /*child2进程终止*/ else if(pid1=0) /*在子进程中*/ printf(“child1s context.n”); sleep(10); /*休眠10秒钟*/ printf(“child1 terminate.n”); exit(0); /*child1进程终止*/ 分析: 上述程序是父进程首先创建一个子进程,若成功,再创建另一个子进程,之后三个进程
5、并发执行。究竟谁先执行,是随机的,可根据执行结果判断。试分析该程序的所有运行结果。注释: fork( ) 调用正确完成时,给父进程返回地是被创建子进程的标识,给子进程返回的是0;创建失败时,返回给父进程的时1;exit(0) 进程终止自己wait(0) 父进程同步等待子进程结束,即无子进程结束,父进程等待。实验分析:首先fork()正确调用,执行父进程,输出parents context parent is waiting the child1 terminate.这个时候wait(0); /父进程同步等待子进程结束,即无子进程结束,父进程等待。执行子进程2,输出child2s context
6、。然后休眠5秒钟,执行子进程1 输出child1s context 休眠10秒钟。进程2首先结束休眠,输出child2 terminate。父进程输出parent is waiting the child2 terminate。子进程1结束休眠,输出child1 terminate,进程1中止自己。父进程child1 terminate,中止自己。在运行的时候会发现,在child1s context 结果出来以后,有一点时间停顿,是因为子进程2还没有结束休眠。同理子进程1也是这样的。(2)管道通信机制通过使用管道实现两个和多个进程之间的通信。所谓管道,就是将一个进程的标准输出与另一个进程的标准
7、输入联系在一起,进行通信的一种方法。同组进程之间可用无名管道进行通信,不同组进程可通过有名管道通信。使用无名管道进行父子进程之间的通信#include <sys/types.h>#include<ctype.h>#include<unistd.h>int pipe( int filedes2); /*创建一个无名管道,filedes0为读通道,filedes1为写通道*/char parent=”a message to pipe communication.n”; /*定义字符串存放于数组中*/main() int pid,chan12; char buf
8、100; pipe(chan1); pid=fork(); /*创建子进程*/if(pid<0) /*如果创建失败*/ printf(“to create child errorn”); exit(1); /*异常终止*/if(pid>0) /*返回值大于0代表父进程*/ close(chan10); /*父进程关闭读通道*/ printf(“parent process sends a message to child.n”); write(chan11,parent,sizeof(parent); close(chan11); /*父进程关闭写通道*/ printf(“pare
9、nt process waits the child to terminate.n”); wait(0);printf(“parent process terminates.n”);else close(chan11); /*子进程关闭写通道*/ read(chan10,buf,100); /*子进程读缓存中的内容*/ printf(“the message read by child process form parent is %s.n”,buf); /*输出读的内容*/ close (chan10); /*子进程关闭读通道*/ printf(“child process terminat
10、esn”);注释:pipe( int filedes2):创建一个无名管道,filedes0为读通道,filedes1为写通道。结果分析:首先程序创建了一个无名管道,如果子进程创建成功,则父进程关闭读通道,输出parent process sends a message to child.然后写信息,关闭写通道,输出parent process waits the child to terminate.等待子进程结束。子进程关闭写通道,然后进行读通道。输出the message read by child process form parent is a message to pipe com
11、munication.关闭子进程,输出child process terminates。父进程终止输出parent process terminates.(3)Linux中的多线程编程threads.c#include <pthread.h>#include <stdio.h>#include <sys/time.h>#include <string.h>#define MAX 10pthread_t thread2;pthread_mutex_t mut;int number=0, i;void *thread1() /*线程1*/ print
12、f ("thread1 : I'm thread 1n"); for (i = 0; i < MAX; i+) printf("thread1 : number = %dn",number); pthread_mutex_lock(&mut); /*声明开始用互斥锁上锁*/ number+; /*同一时间只能被一个进程调用*/ pthread_mutex_unlock(&mut); /*解锁*/ sleep(2); /*休眠2秒*/ printf("thread1 :主函数在等我完成任务吗?n"); pt
13、hread_exit(NULL); /*线程退出*/void *thread2() /*线程2*/ printf("thread2 : I'm thread 2n"); for (i = 0; i < MAX; i+) printf("thread2 : number = %dn",number); pthread_mutex_lock(&mut); number+; pthread_mutex_unlock(&mut); sleep(3); /*休眠3秒*/ printf("thread2 :主函数在等我完成任务
14、吗?n"); pthread_exit(NULL);void thread_create(void) /*创建线程*/ int temp; memset(&thread, 0, sizeof(thread); /comment1 if(temp = pthread_create(&thread0, NULL, thread1, NULL) != 0) /comment2 printf("线程1创建失败!n"); else printf("线程1被创建n"); if(temp = pthread_create(&threa
15、d1, NULL, thread2, NULL) != 0) /comment3 printf("线程2创建失败"); else printf("线程2被创建n");void thread_wait(void) /*等待线程结束*/ if(thread0 !=0) /comment4 pthread_join(thread0,NULL); printf("线程1已经结束n"); if(thread1 !=0) /comment5 pthread_join(thread1,NULL); printf("线程2已经结束n&quo
16、t;); int main() pthread_mutex_init(&mut,NULL); /*用默认属性初始化互斥锁*/ printf("我是主函数哦,我正在创建线程,呵呵n"); thread_create(); printf("我是主函数哦,我正在等待线程完成任务阿,呵呵n"); thread_wait(); return 0;结果分析首先有一个线程的标识符,然后用函数pthread mutex init生成一个互斥锁。然后通过void thread_create(void)函数创建线程。在主函数中首先输出:我是主函数哦,我正在创建线程,
17、呵呵,然后执行thread_create();输出:线程1被创建,线程2被创建。然后输出我是主函数哦,我正在等待线程完成任务阿,呵呵 。然后线程一线程二交替运行,直至最终结束。本实验中我们使用pthread_mutex_init()函数生成互斥锁来解决变量问题,保证一段时间内只有一个线程在执行一段代码。3 注意:Gcc lpthread o thread.out thread.c线程相关操作1) pthread_tpthread_t在头文件/usr/include/bits/pthreadtypes.h中定义: typedef unsigned long int pthread_t; 它是一个
18、线程的标识符。2)pthread_create函数pthread_create用来创建一个线程,它的原型为: extern int pthread_create _P (pthread_t *_thread, _const pthread_attr_t *_attr, void *(*_start_routine) (void *), void *_arg); 第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默
19、认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。3)pthread_join pthread_exit函数pthread_join用来等待一个线程的结束。函数原型为:extern int pthread_join _P (pthread_t _th, void *_thread_return);第一个参
20、数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:extern void pthread_exit _P (void *_retval) _attribute_ (_noreturn_);唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是
21、NULL,这个值将被传递给 thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。在这一节里,我们编写了一个最简单的线程,并掌握了最常用的三个函数pthread_create,pthread_join和pthread_exit。下面,我们来了解线程的一些常用属性以及如何设置这些属性。互斥锁相关互斥锁用来保证一段时间内只有一个线程在执行一段代码。1) pthread_mutex_init 函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如
22、果需要声明特定属性的互斥锁,须调用函数 pthread_mutexattr_init。函数pthread_mutexattr_setpshared和函数 pthread_mutexattr_settype用来设置互斥锁属性。前一个函数设置属性pshared,它有两个取值, PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进程中的线程同步,后者用于同步本进程的不同线程。在上面的例子中,我们使用的是默认属性PTHREAD_PROCESS_ PRIVATE。后者用来设置互斥锁类型,可选的类型有PTHREAD_MUTEX_NORMAL、PTHR
23、EAD_MUTEX_ERRORCHECK、 PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它们分别定义了不同的上锁、解锁机制,一般情况下,选用最后一个默认属性。2) pthread_mutex_lock pthread_mutex_unlock pthread_delay_np pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直至调用pthread_mutex_unlock为止,均被上锁,即同一时间只能被一个线程调用执行。当一个线程执行到pthread_mutex_lock处时,如果该锁此时被另一个线程使用,那此线程被阻塞,即
24、程序将等待到另一个线程释放此互斥锁。注意:1)需要说明的是,上面的两处sleep不光是为了演示的需要,也是为了让线程睡眠一段时间,让线程释放互斥锁,等待另一个线程使用此锁。2)请千万要注意里头的注释comment1-5,如果没有comment1和comment4,comment5,将导致在pthread_join的时候出现段错误,另外,上面的comment2和comment3是根源所在,所以千万要记得写全代码。因为上面的线程可能没有创建成功,导致下面不可能等到那个线程结束,而在用pthread_join的时候出现段错误(访问了未知的内存区)。另外,在使用memset的时候,需要包含string
25、.h头文件。实验三1实验内容与目的 熟悉有关文件的系统调用,学习文件系统的系统调用命令,提高对文件系统实现功能的理解和掌握。使用creat open read write 等系统调用用C语言编程实现复制文件。2注释(1) Int creat(const char *pathname, mode_t mode);返回值:如果正确创建,返回文件的描述符;否则返回1;Pathname是要创建文件的路径名。创建文件时,文件只能以只写方式打开Mode 用来规定该文件的拥有者,小组用户和其他用户的访问权限,要求用按位逻辑加对下列符号常量进行所需的组合(同open函数)。(2) int open(const
26、 char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);int close(int fd);open函数有两个形式.其中pathname是我们要打开的文件名(包含路径名称,缺省是认为在当前路径下面).flags可以去下面的一个值或者是几个值的组合.O_RDONLY:以只读的方式打开文件.O_WRONLY:以只写的方式打开文件.O_RDWR:以读写的方式打开文件.O_APPEND:以追加的方式打开文件.O_CREAT:创建一个文件.O_EXEC:如果使用了O_CREAT而且文件已经存在,
27、就会发生一个错误.O_NOBLOCK:以非阻塞的方式打开一个文件.O_TRUNC:如果文件已经存在,则删除文件的内容.前面三个标志只能使用任意的一个.如果使用了O_CREATE标志,那么我们要使用open的第二种形式.还要指定mode标志,用来表示文件的访问权限.mode可以是以下情况的组合.-S_IRUSR 用户可以读 S_IWUSR 用户可以写S_IXUSR 用户可以执行 S_IRWXU 用户可以读写执行-S_IRGRP 组可以读 S_IWGRP 组可以写S_IXGRP 组可以执行 S_IRWXG 组可以读写执行-S_IROTH 其他人可以读 S_IWOTH 其他人可以写S_IXOTH 其
28、他人可以执行 S_IRWXO 其他人可以读写执行-S_ISUID 设置用户执行ID S_ISGID 设置组的执行ID- 我们也可以用数字来代表各个位的标志.Linux总共用5个数字来表示文件的各种权限.00000.第一位表示设置用户ID.第二位表示设置组ID,第三位表示用户自己的权限位,第四位表示组的权限,最后一位表示其他人的权限. 每个数字可以取1(执行权限),2(写权限),4(读权限),0(什么也没有)或者是这几个值的和.比如我们要创建一个用户读写执行,组没有权限,其他人读执行的文件.设置用户ID位那么我们可以使用的模式是-1(设置用户ID)0(组没有设置)7(1+2+4)0(没有权限,使
29、用缺省)5(1+4)即10705:open("temp",O_CREAT,10705); 如果我们打开文件成功,open会返回一个文件描述符.我们以后对文件的所有操作就可以对这个文件描述符进行操作了.当我们操作完成以后,我们要关闭文件了,只要调用close就可以了,其中fd是我们要关闭的文件描述符.(3)ssize_t read(int fd, void *buffer, size_t count);ssize_t write(int fd, const void *buffer, size_t count); fd是我们要进行读写操作的文件描述符,buffer是我们要写入
30、文件内容或读出文件内容的内存地址.count是我们要读写的字节数. 对于普通的文件read从指定的文件(fd)中读取count字节到buffer缓冲区中(记住我们必须提供一个足够大的缓冲区),同时返回count. 如果read读到了文件的结尾或者被一个信号所中断,返回值会小于count.如果是由信号中断引起返回,而且没有返回数据,read会返回-1,且设置errno为EINTR.当程序读到了文件结尾的时候,read会返回0. write从buffer中写count字节到文件fd中,成功时返回实际所写的字节数.可能用到的头文件#include <stdio.h>#include &l
31、t;sys/types.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>程序:#include <stdio.h> #include <sys/types.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>int main() const char *pathname=”s2.txt”; /* Pathname是要创建文件的路径名*/ int buf10
32、24;int in,out,flag,n; /*定义函数*/ in=open(“s1.txt”,O_RDONLY,S_IRUSR); /*以只读方式打开s1.txt,用户可读*/ out=creat(pathname,S_IWUER); /*创建文件s2.txt,用户可写*/if(in= =-1)printf(“open is errorn”); /*无s1.txt ,打开失败*/if(out= =-1)printf(“creat is errorn”); /*无s2.txt,创建失败*/while(flag=read(in,buf,1024)>0)n=write(out,buf,fla
33、g); /*写入文件内容 */close(in);close(out);return 0;流程图:实验四 模拟内存管理程序(4学时)1、实验目的了解简单的固定大小内存分配方法,掌握分区存储管理技术,了解在分区管理机制下所需的数据结构。2、实验内容1)、将1024K内存按如下块大小分成十个内存块。内存块号 内存块大小 起始地址内存块状态1 512 10 NO2 256 522NO3 256 778NO4 128 1034NO5 128 1162NO6 128 1290NO7 32 1418NO8 32 1450NO9 16 1482NO10 16 1498NO其中,在内存状态中用NO代表该内存块
34、未被分配;用进程名代表该内存块已被分配。2)、编制模拟内存管理程序,根据调入内存的进程大小分别采用最先适应法和最佳适应法分配内存块。最佳适应法,如有一个12K的程序被运行时,它应该被分配到内存块号9,若有200K的程序运行时,应将其调入内存块号2。最先适应法,则是按内存块号的顺序,依次放入各进程名。有关编程请仔细阅读后面的参考流程。3、实验要求1)、要求通过键盘输入若干进程名称和程序所占内存空间的大小,把这些进程分配到内存表中,显示内存分配情况。2)、编制程序可以循环输入,输入某进程结束或某进程添加进来、进程占用存储空间的大小,并显示内存分配情况。3)、当没有区间存放程序时,应有提示。4)、所
35、编写的程序,应有退出功能。5)、每添加、结束一个进程,应有输出显示,输出显示的格式如下:内存块号 内存块大小 起始地址进程名(内存状态)1 512 10 A12 256 522NO3 256 778A24 128 1034A35 128 1162NO6 128 1290NO7 32 1418NO8 32 1450NO9 16 1482NO10 16 1498NO源程序:/*C*/程序所采用的数据结构、符号说明,及采用哪一种内存分配方法Struct memoryInt id; /内存块号Int size; /内存块大小Int start;/起始地址Char name4;/进程名(进程状态),无进
36、程为NOStruct memorysInt count;/当前已分配内存块的个数Struct memory m_memorys10;/内存块数组写出源程序清单,要求附加流程图与注释程序代码:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<string.h>struct memoryInt id; /内存块号Int size; /内存块大小Int start;/起始地址Char name4;/进程名(进程状态),无进程为NO;struct memorysInt count;
37、/当前已分配内存块的个数 Struct memory m_memorys10;/内存块数组;struct memorys * initMemory()struct memorys * m = (struct memorys *)malloc(sizeof(struct memorys);int i;m->count = 0;m->m_memory0.id = 1; /初始化m->m_memory0.size = 512;m->m_memory0.start = 10;strcpy(m->m_,"NO");for(i=1;
38、i<10;i+)m->m_memoryi.id = i+1; if(i=1|i=2)m->m_memoryi.size = 256;else if(i=3|i=4|i=5)m->m_memoryi.size = 128;else if(i=6|i=7)m->m_memoryi.size = 32;elsem->m_memoryi.size = 16;m->m_memoryi.start = m->m_memoryi-1.start+m->m_memoryi-1.size;strcpy(m->m_,"N
39、O");return m;void showMenu(struct memorys* m) /输出内存信息int i;printf("id size start staten");for(i=0;i<10;i+)printf("%2d %3d %4d %sn",m->m_memoryi.id,m->m_memoryi.size,m->m_memoryi.start,m->m_);printf("1.add processn"); /输出选项printf("2.d
40、elete processn");printf("3.exitn");/*最佳适应法分配内存块*/void bestAdapter(struct memorys * m,int size,char *s)if(m->count=10)printf("no room!n");return;int i;for(i=9;i>0;i-)if(strcmp(m->m_,"NO")=0&&m->m_memoryi.size>size)strcpy(m->m_me
41、,s); m->count+;return;void m_add(struct memorys * m) /增加选项printf("to add process!n");int size;char s4;printf("input size :");scanf("%d",&size);printf("input name :");scanf("%s",s);bestAdapter(m,size,s);void m_delete(struct memorys *
42、m) /删除选项printf("to delete process!n");printf("input id :");int id;scanf("%d",&id);if(id>10|id<1)printf("input error!n");return;if(strcmp(m->m_,"NO")!=0)strcpy(m->m_,"NO");elseprintf("no dat
43、a to delete!n");return;int main()int i;struct memorys *memory = initMemory();while(true)showMenu(memory); /输出菜单scanf("%d",&i); /输入switch(i) /选项case 1:m_add(memory);break;case 2:m_delete(memory);break;case 3:exit(-1);break;default:printf("input error!n");break;return 0;/*
44、java*/ 最先适应法package test1;import java.util.*;public class Shiyan4_1 /用二维数组存储数据static String mem = "1", "512", "10", "NO" , "2", "256", "522", "NO" , "3", "256", "778", "NO" , "
45、;4", "128", "1034", "NO" , "5", "128", "1162", "NO" , "6", "128", "1290", "NO" , "7", "32", "1418", "NO" , "8", "32", "1
46、450", "NO" , "9", "16", "1482", "NO" , "10", "16", "1498", "NO" ;private static Scanner sc;public static void print() /输出原内存分配信息System.out.println("NoSizeAddrPID");for (int a = 0; a < 10; a+)
47、for (int b = 0; b < 4; b+) System.out.print(memab + "t");System.out.println(); /换行public static void main(String args) throws InterruptedException /抛出异常String pid;String psize;sc = new Scanner(System.in); print(); /调用输出方法do System.out.println(); /换行System.out.print("Enter process I
48、D:"); pid = sc.next(); /输入IDSystem.out.print("Enter process size:");psize = sc.next(); /输入程序大小System.out.println(); /换行for (int a = 0; a <= 10; a+) if (a = 10) /最先适配算法System.out.println("No enough space for <" + pid + ">.");break; else if (mema3.equals(pid
49、) mema3 = "NO"System.out.println("Process <" + pid + "> has been killed.");break; else if (Integer.parseInt(mema1) > Integer.parseInt(psize) && mema3 = "NO")mema3 = pid;System.out.println("Memory block " + (a+1) + " has allocate
50、d for <" + pid + ">.");break;System.out.println();Thread.sleep(1000); /线程休眠print(); while (true);/ 最佳适应法package test1;import java.util.*;public class Shiyan4_2 /用二维数组存储原信息static String mem = "1", "512", "10", "NO" , "2", "256", "522", "NO" , "3", "256", "778", "NO" , "4", "128", &
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 位长期维修合同范本
- 住院委托协议书范本
- 中考广东英语历真题及答案
- 城市排水管网建设与维护方案
- 多肽药物生产环境与设施监测方案
- 厨余垃圾集中收运与分发管理方案
- 兄弟分家户口协议书
- 个人利润分成协议书
- 住房定房协议书模板
- 个人之间赔付协议书
- 泌尿系CTU检查流程
- 免疫规划知识培训课件PPD
- 巨量千川营销师(初级)认证考试题(附答案)
- 人教版小学《道德与法治》二年级上册全册教案
- 急诊科专科护理常规
- 材料化学专业生涯发展展示
- 2024-2025学年山东省名校考试联盟高二(上)期中数学试卷(含答案)
- 2024-2025学年北京十四中七年级(上)期中语文试卷
- 临电转正式电施工方案
- 平面设计专业职业规划
- 【9语期中】合肥市第三十八中学2024-2025学年九年级上学期期中语文试题
评论
0/150
提交评论