Skip to content

shockley6668/operate-system-Course

Repository files navigation

operate system Course

                           SZTU operate system Course 

                                                   ----author: SHUKUN HUANG

lab1 并发程序设计

一、实验目的与要求:

本实验的主要目的是掌握Linux环境下,多进程之间并发程序设计方法,并通过程序的运行结果来验证分时系统和并发程序设计的优越性。同时,通过上机实践熟悉Linux操作系统子进程创建方法以及任务执行时间测量方法。 本实验包含两个任务:一个任务将一段内容写入磁盘文件中,另一个任务将做求和计算。

  • 1.设计两进程顺序执行程序,并测试所需时间。
  • 2.设计两进程并发执行程序,并测试所需时间。

在以上两个任务基础之上分别测量出写入磁盘文件任务和计算任务所需时间,同时使用操作系统所学的树结构描述出本实验并发执行程序父子进程之间的关系。

二、实验过程及内容:

实验A:

思路描述:使用一个for循环来创建多个子进程。循环从0到9,共执行10次。 在每次循环中,调用fork()函数来创建一个新的子进程。fork()函数会复制当前进程,创建一个新的子进程。在父进程中,fork()函数返回子进程的ID,而在子进程中,fork()函数返回0。如果fork()函数返回一个负值,表示创建子进程失败。在这种情况下,我们使用perror()函数打印出错误信息,并返回1来表示程序执行失败。 如果fork()函数返回0,表示当前进程是子进程。在这种情况下,我们使用getpid()函数获取当前进程的ID,使用getppid()函数获取父进程的ID,并打印出这两个ID。 如果fork()函数返回一个正值,表示当前进程是父进程。在这种情况下,我们使用wait()函数等待子进程的结束。wait()函数会暂停父进程的执行,直到子进程结束。然后,我们使用sleep()函数让父进程休眠5秒钟,以模拟一些耗时的操作。最后,我们使用break语句跳出循环,结束程序的执行。

实验B:

父进程在调用了fork产生了子进程后,继续往下走时便会遇到wait函数,此时父进程就会等待子进程全部代码走完才会继续运行,继续下一个任务。

把wait放在else中。这样就会不等待计算进程执行,马上就创建读写进程,并发执行iotask和computetask,然后最后通过wait()进等待子进程结束返回子进程的进程号来确定各进程的结束时间, 从而计算每个时间和最后结束时间

lab2 进程(线程)同步

实验内容

本实验包含生产者和消费者之间的同步以及读者和写者之间的同步两部分,实现以下功能:

  • 1.有多个生产者和多个消费者线程。我们使用含有n个元素的数组表示n个缓冲区。生产者线程每间隔一段时间例如一秒钟生产一个产品并放入缓冲区中。消费者线程等待生产者线程放入产品后在缓冲区中取出产品。使用信号量机制实现生产者线程和消费者线程之间的同步。
  • 2.有一个或多个写者线程和多个读者线程。读者和写者之间共享一缓冲区(缓冲区可用字符数组表示),写者获得缓冲区访问权限后往缓冲区写入内容。读者获得缓冲区访问权限后从缓冲区中读出内容。当有一个读者获得缓冲区访问权限后,其它读者线程可以访问该缓冲区。而读者与写者之间需要互斥的访问缓冲区。

生产者消费者问题

读者写者问题

显然程序要满足以下要求:

  • 写-写互斥,即不能有两个写者同时进行写操作。
  • 读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
  • 读-读允许,即可以有一个或多个读者在读。

思路: 设置两个信号量,一个为rw,负责用于实现对共享文件的互斥访问,让第一个读进程对其加🔓,最后一个读进程进行解锁。当写进程进入时进行加🔓,写进程结束时候进行解锁,但是这样会出现潜在的问题,只要有源源不断的读进程存在,写进程就要一直阻塞等待,可能会造成“饿死”。所以要引入第二个信号量w,实现写优先。

伪代码如下(具体参考\lab2\readerAndWriter)

rw_lock = 1;	// 互斥量,保证读写数据是串行的
count = 0; 	// 当前执行读操作的读进程有多少个
count_lock = 1;		// 互斥量,保证count变量的访问是串行的
w = 1;    // 互斥量,用来锁住rw_lock
reader(){
    while(1){
        P(w);   // 申请持有rw_lock锁的权利
        P(count_lock)
        if(count==0){
            P(rw_lock)    // 没有读进程上锁,则本读进程上锁
        }
        
        count++
        V(w);    // 拿到rw_lock锁之后才释放w,必须放在count++之后,因为对于读进程而言,count++才算让读进程拿到了rw_lock锁
        V(count_lock)
        
        读数据;
        
        P(count_lock)
        count--
        if(count==0){
            V(rw_lock)    // 如果本进程是最后一个持有锁的读进程,则解锁
        }
        V(count_lock) 
    }
}

这里我们来分析一下读者1->写者1->读者2这种情况。第一个读者1在进行到读文件操作的时候,有一个写者1操作,由于第一个读者1执行了V(w),所以写者1不会阻塞在P(w),但由于第一个读者1执行了P(rw)但没有执行V(rw),写者1将会被阻塞在P(rw)上,这时候再有一个读者2,由于前面的写者1进程执行了P(w)但没有执行V(w),所以读者2将会被阻塞在P(w)上,这样写者1和读者2都将阻塞,只有当读者1结束时执行V(rw),此时写者1才能够继续执行直到执行V(w),读者2也将能够执行下去。

About

SZTU operate system Course

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published