zoukankan      html  css  js  c++  java
  • 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 回顾了线程部分的内容

    参考资料

  • 相关阅读:
    开始我的博客
    POJ 1284:Primitive Roots(素数原根的个数)
    数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)
    NYOJ 85:有趣的数(打表,规律)
    NYOJ 12:喷水装置(二)(贪心,区间覆盖问题)
    HDU 2058:The sum problem(数学)
    HDU 1716:排列2(全排列)
    HDU 2048:神、上帝以及老天爷(错排公式,递推)
    NYOJ 6:喷水装置(一)(贪心)
    BZOJ 2002:Bounce 弹飞绵羊(分块)
  • 原文地址:https://www.cnblogs.com/battlefieldheros/p/8029955.html
Copyright © 2011-2022 走看看