# os **Repository Path**: foisca/os ## Basic Information - **Project Name**: os - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-21 - **Last Updated**: 2021-12-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 操作系统实验 Yep Chingyu😏😏 ## 实验一 Linux下编译、运行和调试 C 程序 ### 实验目的 掌握 Linux 下程序的编辑、编译、运行及调试方法,并能熟练应用。 ### vi 编辑器 ### 程序的调试 ## 实验二 Linux 进程的创建与控制 ### 实验目的 >(1) 加深对进程概念的理解,明确进程与程序的区别。 >(2) 掌握 Linux 进程创建、撤销以及进程并发执行等进程管理方法。 ### 相关知识与系统调用 > (1) exit( ) > 功能:当前进程自我终止,使其进入 ZOMBIE 僵死状态,等待父进程进行善后处理。exit( ) > 是进程正常退出的方法之一,它在头文件“stdlib.h”中声明。 > > (2) fork( ) > 功能:创建子进程,执行两次返回。 > 返回值:-1: 失败,创建不成功 > 0: 在子进程的上下文中 > >0:子进程的标识号,在父进程的上下文中。 > fork 之后父子进程哪一个将先执行是不确定的,取决于内核调度算法。如果要求父子进程 > 之间按照一定顺序执行,则需显式地使用进程同步。 > > (3) wait(0) :父进程调用后自动阻塞,直到子进程执行完撤消时才将父进程唤醒。 > > (4) waitpid(pid):父进程调用后自动阻塞,只有进程号等于 pid 的子进程执行完毕才能被 > 唤醒。 > > (5) getpid( ):获得当前进程的 id 号。 > > (6) getppid( ):获得当前进程的父进程的 id 号。 ## 实验三 Linux 父子进程间数据段的关系 ### 实验目的 掌握并进一步认识并发进程的实质,理解父子进程间数据段的关系。 ## 相关知识 子进程继承父进程的程序、数据等资源;子进程刚创建时,复制父进程的数据段,与父 进程的数据是一样的;在接下来的代码中,父子进程可以修改各自的数据而互不影响。 ## 实验四 Linux 进程的管道通信 ### 实验目的 了解管道通信的特点,熟悉管道通信的概念和原理,掌握管道通信的实现方法。 ### 相关知识与系统调用 >(1) 管道的概念 >管道是用于连接一个读进程和一个写进程的 pipe 文件。逻辑上是管道文件;物理上是 >由文件系统的高速缓冲区构成。管道按 FIFO 方式单向传送消息,只允许在建立者及其子进 >程间使用。 >写进程:以字符流的形式将大量数据送入管道,不断从 pipe 一端写入数据流,在规定的最 >大长度(如 4096 字节)范围内,每次写入的信息长度是可变的。 >读进程:在需要时从 pipe 的另一端读出数据,读出单位长度也是可变的。 >(2) pipe 的建立 >int fd[2] …… pipe(fd) 在系统打开文件表中建立该 pipe 的两个表目 >fd[1]:pipe 入口, 控制写操作 >fd[0]:pipe 的出口, 控制读操作 >(3) pipe 的读写 >写操作:write(fd[1],buf,size) >把 buf 中的长度为 size 字符的消息送入管道入口 fd[1] >buf:存放消息的空间,size :要写入的字符长度 >读操作: read(fd[0],buf,size), 从 pipe 出口 fd[0]读出 size 字符的消息置入 buf >互斥:一个进程正在对 pipe 进行读/写时,另一进程必须等待。 >同步: >发送进程:写 pipe 时,若 pipe 文件长度已经到 4096 字节,仍有部分信息没有写入,则 >进程进入睡眠状态;当读进程收走了全部信息时,被唤醒,将余下信息送入 pipe 中。 >接收进程:读 pipe 时,若 pipe 为空,则进入等待状态。一旦有发送进程执行写操作, >被唤醒。 >(4) 其他相关系统调用 >sleep(n):n 为整数,为秒(s)级。进程调用后将自动阻塞 n 秒,n 秒后自动唤醒,进入就 >绪状态。 >用来锁定文件的某些段或者整个文件,本函数使用的头文件为:“unistd.h”。 >int lockf(int files, int function,long size) >其中:files是文件描述符,function是锁定和 >解锁;1 表示锁定,0 表示解锁。size是锁定和解锁的字节数,若用 0,表示从文件的当前 >位置到文件尾。 ## 实验五 Linux 进程间通信—软中断信号处理 ### 实验目的 基本掌握 Linux 进程软中断通信的基本原理和实现方法。 ### 相关知识与系统调用 > 软中断信号的处理,主要是实现同一用户的各进程之间的通信。 > > (1) kill(pid, sig):发送信号 > > (2) signal(sig, func):指定进程对信号 sig 的处理行为是调用函数 func。 ## 实验六 Linux 进程间通信—消息队列 ### 实验目的 了解消息队列的通信机制及原理,掌握消息通信相关系统调用的使用方法。 ### 相关知识与系统调用 > 消息的创建、发送和接收。多个进程通过访问一个公共的消息队列来交换信息。 > > 消息队列:即消息的一个链表。 > > 任何进程都可以向消息队列中发送消息(消息类型及正文),其他进程都可以从消息队列 > > 中根据类型获取相应的消息。 > > (1) 头文件:“sys/msg.h” > > (2) 打开或创建消息队列:int msgget(key_t key, int msgflg); > > key:消息队列的键 > > IPC_PRIVATE:创建一个私有的消息队列 > > 其他:可被多个进程使用的消息队列 > > msgflg:设置操作类型及访问权限 IPC_CREAT / IPC_EXCL > > (3) 获得或设置消息队列属性:int msgctl( int msgid, int cmd, struct msqid_ds *data); > > (4) 发送消息:int msgsnd(int msgid, const void *msgp, size_t msgsize, int flags); > > 参数: > > msgid:消息队列标识符 id > > msgp:指针,用户自定义缓冲区,可定义成结构体类型,包含两项 long mtype, > > 代表消息类型,char mtext[MTEXTSIZE]; 消息正文 > > msgsize:要发送消息正文的长度 > > mflags:标志,若设置 IPC_NOWAIT 则不等待消息发出就返回 > > 返回值:成功:返回 0 > > 错误:返回-1 (置 errno) > > (5) 接收消息:int msgrcv(int msgid, void *msgp, size_t mtexsize, long msgtype, int flags); > > 参数:与 msgsnd 类似 > > msgtype: >0:只接收指定类型消息的第一个 > > =0:不管什么消息类型都读取队列中第一个数据 > > <0:接收等于或小于其绝对值的最低类型的第一个,如有 5、6、17 > > 三类,若为-6,则获取类型 5 的。 > > 返回值:成功:返回消息正文字节数 > > 错误:返回-1 (置 errno) ## 实验 9 生产者与消费者问题的实现 ### 实验目的 > (1) 理解并发进程的同步与互斥问题的概念和原理。 > > (2) 能熟练应用信号量的 P、V 操作来实现 Linux 进程的同步与互斥。 ### 问题提出与分析 生产者消费者问题分析:一个有限缓冲区和两类线程,它们是生产者和消费者,生产者 把产品放入缓冲区,而消费者是从缓冲区中拿走产品。生产者在缓冲区满时必须等待,直到 缓冲区有空间才继续生产;消费者在缓冲区空时必须等待,直到缓冲区中有产品才能继续读 取。此问题主要考虑的是:缓冲区满或缓冲区空以及竞争条件。 ### 伪码的分析 > empty 为缓冲区中空元素的个数,初值为 n。 > > full 为缓冲区中已生产元素的个数,初值为 0。 > > mutex 为对缓冲区互斥访问时加的锁。 > > int main( ) > { > codebegin > > Productor(); > > Customer(); > > codeend > > } > > //生产者 > > Productor( ): > > while(true) > > { > > P(empty) > > P(mutex) > > //生产产品,往 Buffer[i]中放产品 > > V(mutex) > > V(full) > > } > > //消费者 > > Customer( ): > > While(true) > > { > > P(full) > > P(mutex) > > //从 Buffer[J]取产品,消费产品 > > V(mutex) > > V(empty) > > } ### 相关系统调用 > (1) 线程的创建 > > 相关头文件是“pthread.h”。 > > ① int pthread_create(pthread_t * pthread,const pthread_attr_t *attr, > > void *(*start_routine(*void)),void *arg); > > 创建一个新的线程,新线程创建后执行 start_routine 指定的程序。其中参数 attr > 是用户要创建的线程的属性,当为 NULL 时表示以默认的属性创建线程。 > > arg 是向 start_routine 传递的参数。当成功创建一个新的线程时,系统会自动 > 为新线程分配一个线程 ID 号,并通过 pthread 返回给调用者。 > > ② int pthread_join (pthread- t thread , void *status); > 等待一个线程的结束。调用它的线程将被挂起直到线程 ID 为参数 thread 指定 > 的线程终止。 > > (2) 信号量的操作 > 相关头文件是“semaphore.h”。 > > ① extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value); > > 功能:初始化一个信号量 > > 参数:sem:为指向信号量结构的一个指针; > > pshared:不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享; > > value:给出了信号量的初始值。 > > ② int sem_wait(sem_t * sem); > > 功能:t 阻塞当前线程,直到信号量 sem 的值大于“0”。解除阻塞后,将 sem 的值 > 减“1”,表明公共资源经过使用后减少。 > > ③ int sem_post(sem_t * sem); > > 功能:使信号量 sem 的值加“1”。