• 2017-2018-1 20155324 《信息安全系统设计基础》第八周学习总结


    2017-2018-1 20155324 《信息安全系统设计基础》第八周学习总结

    第八周课下作业2(课上没完成的必做)

    基于socket 使用教材的csapp.h csapp.c,实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
    服务器响应消息格式是
    “
    客户端IP:XXXX
    服务器实现者学号:XXXXXXXX
    当前时间: XX:XX:XX
    ”
    上方提交代码
    提交一个客户端至少查询三次时间的截图测试截图
    提交至少两个客户端查询时间的截图测试截图
    

    书上相关代码

    多线程
    /* 
     * echoserveri.c - An iterative echo server 
     */ 
    /* $begin echoserverimain */
    #include "csapp.h"
    
    void echo(int connfd);
    
    int main(int argc, char **argv) 
    {
        int listenfd, connfd, port, clientlen;
        struct sockaddr_in clientaddr;
        struct hostent *hp;
        char *haddrp;
        if (argc != 2) {
        fprintf(stderr, "usage: %s <port>
    ", argv[0]);
        exit(0);
        }
        port = atoi(argv[1]);
    
        listenfd = Open_listenfd(port);
        while (1) {
        clientlen = sizeof(clientaddr);
        connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
    
        /* determine the domain name and IP address of the client */
        hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, 
                   sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        haddrp = inet_ntoa(clientaddr.sin_addr);
        printf("server connected to %s (%s)
    ", hp->h_name, haddrp);
    
        echo(connfd);
        Close(connfd);
        }
        exit(0);
    }
    /* $end echoserverimain */
    

    echoclient.c:

    /*
     * echoclient.c - An echo client
     */
    /* $begin echoclientmain */
    #include "csapp.h"
    
    int main(int argc, char **argv) 
    {
        int clientfd, port;
        char *host, buf[MAXLINE];
        rio_t rio;
    
        if (argc != 3) {
        fprintf(stderr, "usage: %s <host> <port>
    ", argv[0]);
        exit(0);
        }
        host = argv[1];
        port = atoi(argv[2]);
    
        clientfd = Open_clientfd(host, port);
        Rio_readinitb(&rio, clientfd);
    
        while (Fgets(buf, MAXLINE, stdin) != NULL) {
        Rio_writen(clientfd, buf, strlen(buf));
        Rio_readlineb(&rio, buf, MAXLINE);
        Fputs(buf, stdout);
        }
        Close(clientfd);
        exit(0);
    }
    /* $end echoclientmain */
    

    遇到的问题:怎么导入csapp.h

    下载并解压后(以 root 身份登录)应该是一个code的文件夹,在其子文件夹includesrc中分别可以找到csapp.hcsapp.c两个文件,把这两个文件拷贝到文件夹/usr/include里面,并在csapp.h文件中 #endif 之前加上一句 #include<csapp.h> ,然后编译时在最后加上 lpthread 例如:gcc main.c -lpthread 就可以编译了。

    家庭作业4.47

    取指阶段 icode:ifun = D:0
    valP<-PC+1
    译码阶段:valB<-R[%ebp]
    执行阶段:valE<-valB+4
    访存阶段:valM<-M4[valB]
    写回阶段:R[%esp]<-valE R[%ebp]<-valM
    

    家庭作业4.48

    取指阶段:icode:ifun = M1[PC] = C:0 
    rA:rB<-M1[PC+1]
    valC<-M4[PC+2]
    valP<-PC+6   
    译码阶段:valB<-R[rB]   
    执行阶段:valE<-valB+valC
    SetCC
    访存阶段:-  
    写回阶段  R[rB]<-valE 
    

    教材学习内容总结

    教材第十二章学习

    什么是进程(Process)?

    进程就是一段程序的执行过程。
    

    进程的概念主要有两点:

    • 第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程中调用的指令和本地变量。

    • 第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。

    进程的状态: 进程有三个状态,就绪,运行和阻塞。

    • 就绪状态其实就是获取了除cpu外的所有资源,只要处理器分配资源马上就可以运行。

    • 运行态就是获取了处理器分配的资源,程序开始执行。

    • 阻塞态,当程序条件不够时,需要等待条件满足时候才能执行,如等待I/O操作的时候,此刻的状态就叫阻塞态。

    进程的特征:

    • 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;

    • 并发性:任何进程都可以同其他进程一起并发执行;

    • 独立性:进程是系统进行资源分配和调度的一个独立单位;

    • 结构性:进程由程序、数据和进程控制块三部分组成。

    什么是线程(thread)?

    定义:线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
    

    线程起源:

    • 在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的一块内存,使得各个进程之间内存地址相互隔离。

    • 后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了,于是就发明了线程。

    线程特征:

    • 线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),一个线程可以创建和撤销另一个线程;

    • 通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源。在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。

    进程 和 线程的区别
    1、一个程序至少有一个进程,一个进程至少有一个线程;
    
         进程是资源分配的最小单位,线程是CPU调度的最小单位。
    
    2、资源(内存、寄存器等)分配给进程,进程在执行过程拥有独立的内存空间,而同一进程下的所有线程共享所有资源,从而提高程序的运行效率;
    
    3、处理机分配给线程,即处理机真正运行的是线程;
    
    4、线程在执行过程中,需要协作同步。不同线程间的要利用通信协议来实现同步。
    

    I/O多路复用

    image

    I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。

    image

    基于 I/O 多路复用的并发编程
    • I/O多路复用技术的基本思路:使用select函数,要求内核挂起进程,只有在一个或多个I/O事件发生后,才将控制返回给应用程序

    • 状态机就是一组状态、输入事件和转移,转移就是将状态和输入时间映射到状态,自循环是同一输入和输出状态之间的转移。

    • I/O 多路复用技术的优劣

    优点:

    • 它比基于进程的设计给了程序员更多的对程序行为的控制。

    • 一个基于 I/O 多路复用的事件驱动服务器是运行在单一进程上下文中的,因 此每个逻辑流都能访问该进程的全部地址空间。

    缺点:

    • 编码复杂且不能充分利用多核处理器。

    image

    线程控制及相关系统调用

    1. 内核级线程:切换由内核控制,当线程进行切换的时候,由用户态转化为内核态。切换完毕要从内核态返回用户态;可以很好的利用smp,即利用多核cpu。windows线程就是这样的。

    2. 用户级线程内核的切换由用户态程序自己控制内核切换,不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核Cpu,目前Linux pthread大体是这么做的。

    线程的实现可以分为两类:用户级线程(User-Level Thread)和内核线线程(Kernel-Level Thread),后者又称为内核支持的线程或轻量级进程。在多线程操作系统中,各个系统的实现方式并不相同,在有的系统中实现了用户级线程,有的系统中实现了内核级线程。

    用户进程的优点:

    (1) 线程的调度不需要内核直接参与,控制简单。

    (2) 可以在不支持线程的操作系统中实现。

    (3) 创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多。

    (4) 允许每个进程定制自己的调度算法,线程管理比较灵活。这就是必须自己写管理程序,与内核线程的区别

    (5) 线程能够利用的表空间和堆栈空间比内核级线程多。

    (6) 同一进程中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起。另外,页面失效也会产生同样的问题。

    多线程程序中的变量共享

    每个线程和其他线程一起共享进程上下文的剩余部分。包括整个用户虚拟地址空间,是由只读文本、读/写数据、堆以及所有的共享库代码和数据区域组成的。线程也共享同样的打开文件的集合。

    • 全局变量:虚拟存储器的读/写区域只会包含每个全局变量的一个实例。

    • 本地自动变量:定义在函数内部但没有static属性的变量。

    • 本地静态变量:定义在函数内部并有static属性的变量。

    用信号量同步线程

    进度图是将n个并发线程的执行模型化为一条n维笛卡尔空间中的轨迹线,原点对应于没有任何线程完成一条指令的初始状态。

    转换规则:
    合法的转换是向右或者向上,即某一个线程中的一条指令完成
    两条指令不能在同一时刻完成,即不允许出现对角线
    程序不能反向运行,即不能出现向下或向左
    

    信号量定义:

    type semaphore=record
    count: integer;
    queue: list of process
    end;
    var s:semaphore;
    

    读者—写者问题:
    (1)读者优先,要求不让读者等待,除非已经把使用对象的权限赋予了一个写者。
    (2)写者优先,要求一旦一个写者准备好可以写,它就会尽可能地完成它的写操作。
    (3)饥饿就是一个线程无限期地阻塞,无法进展。

    HTML静态化

    效率最高、消耗最小的就是纯静态化的html页面,所以尽可能使网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,无法全部手动去挨个实现,于是出现了常见的信息发布系统CMS,像常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。

    阻塞 VS 非阻塞

    阻塞/非阻塞, 它们是程序在等待消息(无所谓同步或者异步)时的状态。

    阻塞

    阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
    有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。
    对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。

    socket接收数据函数recv是一个阻塞调用的例子。
    当socket工作在阻塞模式的时候, 如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止。

    非阻塞

    非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

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

    • 问题1:一个头文件csapp.h,编译代码时遇到csapp不存在的问题
    • 问题1解决方案:下载并解压后(以 root 身份登录)应该是一个code的文件夹,在其子文件夹includesrc中分别可以找到csapp.hcsapp.c两个文件,把这两个文件拷贝到文件夹/usr/include里面,并在csapp.h文件中 #endif 之前加上一句 #include<csapp.h> ,然后编译时在最后加上 lpthread 例如:gcc main.c -lpthread 就可以编译了。

    代码托管

    其他(感悟、思考等,可选)

    学习了系统的输入、输出,了解了一些I/O函数,只看书的页数的话,本章的页数很少,相较于之前几周感觉轻松不少。但是,页数少并不意味着不重要或是用时少,认真去理解系统的输入、输出对于我们理解程序的运行至关重要,而每一个函数的参数、不同情况的返回值也需要我们仔细研读。

    学习进度条

    代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
    目标 5000行 30篇 400小时
    第一周 85/85 1/1 5/5
    第二周 150/230 1/2 10/15
    第三周 50/280 1/3 7/22
    第四周 70/350 1/4 5/27
    第五周 100/450 2/6 5/32
    第六周 50/500 1/7 10/42
    第七周 70/570 2/9 10/55
    第八周 80/650 1/10 8/63

    尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
    耗时估计的公式
    :Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

    参考:软件工程软件的估计为什么这么难软件工程 估计方法

    • 计划学习时间:XX小时

    • 实际学习时间:XX小时

    • 改进情况:

    (有空多看看现代软件工程 课件
    软件工程师能力自我评价表
    )

    参考资料

  • 相关阅读:
    物理机安装Centos7
    rust网站
    windows10安装ubuntu双系统教程
    在win10+Ubuntu双系统下,完美卸载Ubuntu
    C# Lambda 学习笔记
    git unable to resolve reference 'refs/remotes/gitee/20210825-add-Projet-coreScene': reference broken
    git如何获取远端仓库新分支
    编码规范
    新萝卜家园GHOST WIN7系统32,64位官方版下载
    Semaphore实战
  • 原文地址:https://www.cnblogs.com/wang5324/p/7823428.html
Copyright © 2020-2023  润新知