20155223 《信息安全系统设计基础》第13周学习总结

20155223 《信息安全系统设计基础》第13周学习总结

练习题回答

12.1

父进程派生出子进程时,子进程自动获得一个已连接描述符的副本,并将相关文件表中的引用计数从1加到2。.父进程关闭其本身的描述符副本时,引用数减1,但是不为0,。只有引用数为0时,系统才会关闭文件,所以子进程依然保持连接端打开。

12.2

当一个进程终止时,内核将自动关闭所有打开的描述父。所以,当子进程退出时,其已连接文件描述符的副本也随之被删除。

12.3

假设EOF在一个描述符上为真,那么读操作将立即返回一个零返回码,以示EOF。所以,Ctrl+D会导致函数select返回,准备好的集合中有描述符0。

12.4

因为变量pool.read_set既可当输入参数又可以当输出参数,所以必须要在每一次调用select前重新初始化变量pool.read_set。

12.5

因为线程都运行在同一个进程中,他们共享同一个描述符表。因此无论有多少个线程用这个已连接描述符,文件表的引用数都等于1。所以只用一个close操作就可以释放与这个文件表相关的所有内存资源了。

12.6

  • A.表格填写
变量实例 被主线程引用? 被对等线程0引用? 被对等线程1引用?
ptr
cnt
i.m
msgs.m
myid.p0
myid.p1
  • 说明:
    ptr是全局变量
    cnt是静态变量,被两个对等线程读写
    i.m是本地自动变量,对等线程可以获得其值,但是不会在栈中引用它
    msgs.m是本地自动变量,被两个对等线程通过ptr间接引用
    myid.p0和myid.p1是本地自动变量,分别驻留在线程0和线程1当中。
  • B.变量ptr、cnt、msgs.m被主线程和两个对等线程引用,所以这三个线程是共享的。

12.7

表格填写:
%rdx1:—;0;—;—;—;—;1;1;1;—;
%rdx2:—;—;—;0;1;1;—;—;—;1;
cnt:0;0;0;0;0;1;1;1;1;1;
变量cnt最终只有一个不正确的值1。

12.8

通过画图可以看出:A、C的轨迹线避开了临界区,而B的轨迹线插入了临界区。所以A、C是安全的,B是不安全的。

12.9

解答:
A.p=1,c=1,n>1:是,必须使用互斥锁,因为生产者和消费者的访问是并发的。
B.p=1,c=1,n=1:不是,在这种情况下就不需要互斥锁信号量。一个非空缓冲区等价于一个满载缓冲区。当缓冲区包含一个项目时,生产者被阻塞;反之,消费者被阻塞。所以在任意时刻,只有一个线程可以访问缓冲区,因此不需要互斥锁。
C.p>1,c>1,n=1:不是,原因同B。

教材内容学习总结:第12章

三种并发方式

使用应用级并发的应用程序成为并发程序。现在操作系统提供了三种基本的构造并发程序的方法:

  • 进程:每个逻辑控制流都是一个进程,由内核来调度和维护。进程间通信依靠进程间通信机制。
  • I/O多路复用:应用程序在一个进程的上下文中显式地调度它们自己的逻辑控制六,所有流应为程序是个单独的进程而共享同一个地址空间。
  • 线程:运行在一个单一进程上下文中的逻辑流,由内核进行调度。可以将线程看成前两种的混合体。

进程并发

进程是构造并发程序的最简单方法。使用熟悉的函数如fork、exec、waitpid等。例如,一个构造并发服务器的自然方法就是,在父进程中接受客户端的连接请求,然后创建一个新的子进程来为每个新客户端提供服务。
进程并发可以让父、子进程之间共享文件表,但是各个子进程之间不共享用户地址空间。一个子进程不可能会将另一个子进程的虚拟内存覆盖掉,但是各进程之间的通信仰赖进程间通信机制,使进程并发式程序比其他两种更慢。

I/O多路复用并发

I/O多路复用使用select函数,要求内核挂起进程,只有存在一个或多个I/O时间发生后,才将控制返回给应用程序。
I/O多路复用方式使得程序员可以更多地控制程序行为。一个基于I/O多路复用的并发服务器是运行在单一进程的上下文中的,因此每个逻辑流都可以访问该进程的全部地址空间。但是此类并发程序编码量特大,难以进行快速修改。而当单位时间内访问程序的次数增加,I/O多路复用服务器的代码量也必须增加,不然极易被过多的访问量冲击而损坏。

线程并发

线程是I/O多路复用和进程的混合体。线程不存在进程那样的父子结构,每个对等线程都可以读写相同的共享数据。因为线程上下文比进程上下文小得多,因此线程上下文的切换比进程的要快很多。

线程相关函数

  • 创建线程:pthread_create。新创建的线程通过函数pthread_self来获取自身的线程ID。
  • 终止线程:pthread_exit。线程会显式地终止,如果是主线程调用此函数,那么这个线程必须等待其他所有对等线程终止,然后再终止主线程和整个进程。终止当前进程用函数pthread_cancel。
  • 回收线程资源:pthread_join。此函数会阻塞,直到目标线程终止。
  • 分离线程:pthread_detach。
  • 线程初始化:pthread_once。

用信号量同步线程

共享变量是线程之间共享信息的一个重要手段,但是共享变量也引入了同步错误的可能性。同步错误是一种同步不同执行线程问题。解决这种问题的方案是信号量这一特殊类型变量。
信号量是一种全局非负整数型变量,信号量只能通过两种操作:P和V来处理。
P操作:当信号量非零时,信号量减一。当信号量为0时,系统挂起这个线程,直到信号量重新变为非0。
V操作:与P操作相反。
P操作和V操作保证信号量不为负。
使用信号量来实现互斥的基本思想是将每个共享变量(或者一组相关的共享变量)与一个初始值为1的信号量联系起来,然后用P操作和V操作将相应地临界区包围起来。以这种方式来保护变量的信号量叫二元信号量,因为它的值总是0和1。以提供互斥为目的的二元信号量常常也成为互斥锁。在互斥锁上执行P操作叫加锁,执行V操作叫解锁。

利用信号量来调度共享资源

  • 生产者——消费者问题

  • 读者——写者问题
    一组并发的线程要访问一个共享对象。有些线程只读对象,而其他线程只修改对象。读对象的是读者,修改对象的叫写者。写者必须独占对象,读者可以和其他读者一同共享对象。一般来说,有无限多个并发的读者和写者。

教材学习中的问题和解决过程

  • 问题1:读者——写者问题有两大类:读者优先、写者优先。那么怎么用信号量来解决这类问题?
  • 问题1的解决方案:
    这是我上网找的一份代码。
    使用AW表示正在写的线程,WW表示正在等待写的线程。
    AR表示正在读的线程,WR表示正在读的线程。
    使用锁lock对AW WW AR WR进行互斥访问。
    okToread okTowrite为条件变量。
AR = 0;
AW = 0;
WR = 0;
WW = 0;
Condition okToRead;
Condition okToWrite;
Lock lock;
void reader()
{
    while(true)
    {
        startread();  //等,直到没有在等待或正在写的写者
        read;
        doneread();   //如果有等待的写者,唤醒写者
    }
}
void startread()
{
    lock.acquire();
    while((WW+AW)>0)  //如果有在等待或正在写的写者,读者阻塞
    {
        WR++;
        okToread.wait(&lock);
        WR--;
    }
    AR++;
    lock.release();
 }
 void doneread()
 {
     lock.require();
     AR--;
     if(AR==0 && WW>0)     //如果正在读的读者为零且有在等待的写者,唤醒写者
         okToWrite.signal();
     lock.release();
 }

void writer()
{
    while(true)
    {
        startwrite(); //等,直到没有正在写的读者或写者
        write;
        donewrite();  //如果有正在等待的写者,唤醒,否则如果有正在等待的读者,唤醒
     }
 }
 void startwrite()
 {
     lock.require();
     while((AR + AW) >0 )  //如果有正在写的读者或写者,写者等待
     {
         WW++;
         okTowrite.wait(&lock);
         WW--;
      } 
      AW++;
      lock.release();
  }
  void donewrite()
  {
      lock.require();
      AW--;      
      if(WW>0)          //如果有写者等待,唤醒写者
          okTowrite.signal();
      else if(WR>0)    //如果有读者等待,唤醒读者
          okToread.broadcast();
      lock.release();
   }

能帮助我理解怎么用信号量来解决读者写者问题。

第12章关键字

进程并发、I/O多路复用并发、线程并发、信号量解决互斥和共享资源。

代码调试中的问题和解决过程

  • 问题1:从网上寻找的部分代码不能在虚拟机中实现,尽管已经排除掉所有语法错误、编译错误、存储错误,仍然是不能出结果。
  • 问题1的解决方案:后确认是系统版本问题,我使用的乌班图系统版本很低,有些输入输出格式不兼容。

代码托管

结对及互评

本周结对学习情况

20155207
结对照片
结对学习内容
- 第12章线程部分
- 实验五

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 31/31 1/1 20/20
第三周 24/55 2/3 24/44 知道浮点数怎么储存的
第四周 177/328 2/5 17/61 现在我的C语言程序也会在Linux命令行下使用了:*)
第五周 54/382 2/7 18/79 复习一遍汇编语言
第七周 2360/2722 1/8 12/91
第八周 624/3344 2/10 19/110 了解多线程和多进程
第九周 1112/4456 3/13 15/125 学习怎么实现pwd命令
第十一周 157/4613 2/15 10/135 在紧急情况下恢复不可使用的虚拟机
第十三周 999/5471 2/17 17/152 回顾了线程部分的内容

参考资料

posted @ 2017-12-16 16:35  陆基神盾  阅读(256)  评论(1编辑  收藏  举报