欢迎光临散文网 会员登陆 & 注册

操作系统实践报告

2023-07-06 21:54 作者:---狐阿桔---  | 我要投稿

Job6/sh4

题目要求:

重新编写makefile;

实现连接多条命令;

编写测试用例。

解决思路:

重新编写makefile:

根据教学视频所讲述模板进行编写,得到自动生成依赖关系makefile文件。在 Makefile.dep 中定义依赖关系,然后在 Makefile 文件中引用依赖关系进行编 译等操作。

实现连接多条命令:

创建管道,前一个命令的输出作为下一个命令的输入,管道的创建和关闭依靠函数对命令数组进行遍历,将命令的输入输出连接起来,在子进程中,函数执行当前命令,并将输出写入管道;在父进程中,函数等待子进程执行完毕,并将管道的输入端设置为下一个命令的输入。

编写测试用例:

对几种测试用例进行实现。

关键代码:

重写makefile:




exec_cmd函数实现


运行结果:

test_parse_cmd_1 pass
test_parse_cmd_2 pass
test_parse_pipe_cmd_1 pass
test_parse_pipe_cmd_1 pass
test_exec_cmd pass
test_exec_pipe_cmd pass
All test have passed!
>pwd
current working directory:/root/os/job6/sh4
>ls
Makefile Makefile.dep cmd.c cmd.h cmd.o main.c main.o parse.c
parse.h parse.o readme.md sh4 test test.in test.out
>exit


Job8/pc1.c

题目要求:

  • 系统中有3个线程:生产者、计算者、消费者

  • 系统中有2个容量为4的缓冲区:buffer1、buffer2

  • 生产者

    • 生产'a'、'b'、'c'、‘d'、'e'、'f'、'g'、'h'八个字符

    • 放入到buffer1

    • 打印生产的字符

  • 计算者

    • 从buffer1取出字符

    • 将小写字符转换为大写字符,按照 input:OUTPUT 的格式打印

    • 放入到buffer2

  • 消费者

    • 从buffer2取出字符

    • 打印取出的字符

  • 程序输出结果(实际输出结果是交织的) a b c ...  a:A  b:B  c:C  ...      A      B      C      ...

解决思路:

定义一个buffer结构体,用来存储buffer1与buffer2状态,定义buffer_is_empty(struct array a)buffer_is_full(struct array a)get_item(struct array *a)put_item(struct array *a, char item)函数。

总共有三个角色,他们的关系是:计算者相当于生产者的消费者,“消费者”相当于计算者的消费者。

1.生产者产生字符后,查看buffer1的锁状态,加锁,之后判断buffer1是否为满,满则阻塞等待,反之放入缓冲区buffer1,之后唤醒等待的计算者线程,解开锁。

2.计算者被唤醒后,获取buffer1的锁,加锁,判断buffer1是否为空,如果空则阻塞等待,反之取出一个字符,转化为大写形式。之后再唤醒生产者,释放锁。接下来,它作为消费者的生产者,查看buffer2的锁状态,加锁,之后判断buffer2是否为满,满则阻塞等待,反之将字符放入缓冲区buffer2,之后唤醒等待的消费者线程,解开锁。

3.消费者被唤醒后,获取buffer2的锁,加锁,判断buffer2是否为空,如果空则阻塞等待,反之取出一个字符,输出到屏幕上,之后唤醒消费者,解开锁。

关键代码:


运行结果:

produce item: a
produce item: b
a:A
produce item: c
   consume item: A
b:B
produce item: d
   consume item: B
c:C
produce item: e
   consume item: C
d:D
produce item: f
   consume item: D
e:E
produce item: g
   consume item: E
f:F
produce item: h
   consume item: F
g:G
   consume item: G
h:H
   consume item: H


Job8/pc2.c

题目要求:

使用信号量解决生产者、计算者、消费者问题 功能与 job8/pc1.c相同

解决思路:

引入信号量结构体,并且定义多个信号量,通过sema_init()对信号量进行初始化,sema_wait()进行等待,sema_signal()进行释放。

总共有三个角色,他们的关系是:计算者相当于生产者的消费者,“消费者”相当于计算者的消费者,按一定的逻辑执行PV操作。

生产者首先执行 sema_wait(&empty_buffer1_sema)函数,如果buffer1存在空闲位置, empty_buffer1_sema减1,对buffer1进行加锁,加入字符后进行解锁。之后执行sema_signal(&full_buffer1_sema);进行加1操作后,唤起计算者进程。

唤起计算者进程后,首先执行sema_wait(&full_buffer1_sema);函数,如果buffer1存在值,则full_buffer1_sema减1,加buffer1的锁,取字符转换为大写形式,解开锁,之后执行sema_signal(&empty_buffer1_sema);此时empty_buffer1_sema加1,唤醒等待的生产者线程。之后作为生产者,向buffer2写字符,首先执行sema_wait(&full_buffer2_sema) 函数,判断是否buffer2有值,如果等到有值的情况,则full_buffer2_sema减1,加buffer1的锁,取字符转换为大写形式,解开锁,再执行ema_signal(&empty_buffer2_sema),此时empty_buffer2_sema加1,唤醒等待的消费者线程。

消费者首先执行sema_wait(&full_buffer2_sema);buffer2进行判断,如果有值,则full_buffer2_sema减1,加buffer2的锁,取字符打印输出,解开锁,再执行sema_signal(&empty_buffer2_sema),此时empty__buffer2_sema加1,唤醒等待的计算者线程。

关键代码:


运行结果:

produce item: a
produce item: b
produce item: c
               compute item before: a
               compute item after : A
produce item: d
                                       consume item: A
               compute item before: b
               compute item after : B
produce item: e
                                       consume item: B
               compute item before: c
               compute item after : C
produce item: f
                                       consume item: C
               compute item before: d
               compute item after : D
produce item: g
                                       consume item: D
               compute item before: e
               compute item after : E
produce item: h
                                       consume item: E
               compute item before: f
               compute item after : F
               compute item before: g
               compute item after : G
                                       consume item: F
               compute item before: h
               compute item after : H
                                       consume item: G
                                       consume item: H


Job9/pfind.c

题目要求:

功能与 sfind 相同

要求使用多线程完成

主线程创建若干个子线程

主线程负责遍历目录中的文件

遍历到目录中的叶子节点时

将叶子节点发送给子线程进行处理

两者之间使用生产者消费者模型通信

主线程生成数据

子线程读取数据

解决思路:

分不同情况,如果路径为文件,则对文件进行查找是否有包含指定的字符串,输出行。如果路径为目录,则遍历目录与其子目录,将得到的文件路径与搜索的字符串添加到任务队列中。

创建WORKER_NUMBER个子进程,不同子进程从任务队列中获取任务并执行,即对指定文件进行查找。当任务队列为空时,等待新的任务加入。

主线程完成遍历后,根据WORKER_NUMBER添加标记,表示所有任务完成,子线程得到标记后,自动退出线程。

关键代码:


运行结果:

root@lisongqi-virtual-machine:/home/lisongqi/桌面/operating-system-experiment-ma
ster/job10# cc pfind.c -o pfind -lpthread
root@lisongqi-virtual-machine:/home/lisongqi/桌面/operating-system-experiment-ma
ster/job10# ./pfind test main
test/hello/hello.c: int main() {
test/world/world.c: int main()
root@lisongqi-virtual-machine:/home/lisongqi/桌面/operating-system-experiment-ma
ster/job10# ./pfind test int
test/hello/hello.c: int main() {
test/hello/hello.c:  printf("hello");
test/world/world.c: int main()
test/world/world.c:  printf("world");

Job11/http服务器

题目要求:

完成多进程版本的 httpd

放置在 job10/http/concurrent 目录下

解决思路:

主函数首先解析命令行参数,获取要监听的 IP 地址和端口号。然后使用 tcp_listen 函数创 建一个 TCP 服务器,该服务器会监听指定的 IP 地址和端口号。 在服务器开始循环等待客户端连接时,使用 tcp_accept 函数接受一个新的连接,然后使用 fork 函数创建一个子进程来处理客户端连接。在子进程中,调用 http_handler 函数来处 理客户端的 HTTP 请求,并在处理完毕后关闭连接。

通过 http_parse_req 函数解析客户端发送的请求,获取请求的路径。

判断路径是否以 "/app/" 开头,如果是则认为客户端请求的是一个 CGI 脚本,需要执行该脚本 并将输出发送给客户端。

如果路径不是以 "/app/" 开头,则判断路径对应的是一个文件还是目录,如果是目录则调用 generate_directory_listing 函数生成一个 HTML 目录列表并发送给客户端,如果是文 件则直接将文件内容发送给客户端。

在向客户端发送响应时,使用分块传输编码(Chunked Transfer Encoding)进行传输,这是 一种将消息分块传输的方式,可以在发送大量数据时提高传输效率。

关键代码

http.c

main.c

运行结果:

http://localhost:8080/
Hello World!
/a.html
/b.html
/c.html
/source
/app/now
/app/show_env?name=tom&age=10
/app/list_student
/add_student.html
/remove_student.html


操作系统实践报告的评论 (共 条)

分享到微博请遵守国家法律