2017-2018-1 20155204 《信息安全系统设计基础》第八周学习总结
教材学习内容总结
-
并发:逻辑控制流在时间上重叠
-
并发程序:使用应用级并发的应用程序称为并发程序
-
三种基本的构造并发程序的方法:
(1)进程,用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制。
(2)I/O多路复用,应用程序在一个进程的上下文中显式的调度控制流。逻辑流被模型化为状态机。
(3)线程,运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。 -
关于进程的优劣
注意:进程的模型:共享文件表,但不是共享用户地址空间。 优点:一个进程不可能不小心覆盖两一个进程的虚拟存储器。
缺点:独立的地址空间使得进程共享状态信息变得更加困难。进程控制和IPC的开销很高。Unix IPC是指所有允许进程和同一台主机上其他进程进行通信的技术,包括管道、先进先出(FIFO)、系统V共享存储器,以及系统V信号量。 -
事件驱动器的设计优点:
(1)比基于进程的设计给了程序员更多的对程序行为的控制
(2)运行在单一进程上下文中,因此,每个逻辑流都能访问该进程的全部地址空间,使得流之间共享数据变得很容易。
(3)不需要进程上下文切换来调度新的流。
缺点:
(1)编码复杂
(2)不能充分利用多核处理器 -
线程安全:当且仅当被多个并发线程反复地调用时,它会一直产生正确的结果。
线程不安全:如果一个函数不是线程安全的,就是线程不安全的。 -
线程不安全的类:
(1)不保护共享变量的函数
(2)保持跨越多个调用的状态的函数。
(3)返回指向静态变量的指针的函数。解决办法:重写函数和加锁拷贝。
(4)调用线程不安全函数的函数。
教材学习中的问题和解决过程
- 问题1:如何解决死锁?
- 问题1解决方案: 不让死锁发生:
静态策略:设计合适的资源分配算法,不让死锁发生---死锁预防;
动态策略:进程在申请资源时,系统审查是否会产生死锁,若会产生死锁则不分配---死锁避免。
b.让死锁发生:
进程申请资源时不进行限制,系统定期或者不定期检测是否有死锁发生,当检测到时解决死锁----死锁检测与解除。
课上实践内容补做
- 把第一个练习中的代码在X86-64(Ubuntu)中反汇编,给出汇编代码和机器码的截图把X86-64汇编翻译成Y86-64汇编,并给出相应机器码的截图(使用附件中的Y86-64模拟器)
-
步骤一:利用
objdump -d
进行反汇编
-
步骤二:将X86-64编译Y86-64。
-
其中安装Y86-64模拟器部分有参考狄惟佳同学的博客,其余部分没有出错很顺利。
- socket编程,详见下方课下练习。
课下练习
一、
- 完成家庭作业4.47,4.48,4.49
- 相应代码反汇编成X86-64汇编
- 把上述X86-64汇编翻译成Y86汇编,并给出相应机器码
步骤:
- 跟课上实践类似,没有太大难度。
二、
- 把课上练习3的daytime服务器分别用多进程和多线程实现成并发服务器并测试
步骤:
代码:(多进程为例)
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#define RIO_BUFSIZE 8192
typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];
}rio_t;
#define MAXLINE 200
int main(int argc,char **argv){
int clientfd,port;
char *host,buf[MAXLINE];
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
char str1[MAXLINE]="客户端IP:";
char str2[MAXLINE]="服务器实现者学号:20155204";
char str3[MAXLINE]="当地时间:";
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);
while(1){
recv(clientfd,rbuf,MAXLINE,0);
printf("%s",str1);
puts(host);
printf("%s",str2);
putchar('
');
printf("%s",str3);
puts(rbuf);
close(clientfd);
exit(0);
}
}
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define MAXLINE 200
#define RIO_BUFSIZE 8192
typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];
}rio_t;
typedef struct sockaddr SA;
typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;
void sigchld_handler(int sig){
pid_t pid;
int stat;
while((pid = waitpid(-1,&stat,WNOHANG))>0){
printf("child %d terminated
",pid);
}
return;
}
int main(int argc,char **argv){
int listenfd,connfd,port,clientlen;
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp;
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
time_t lt;
tm *local;
char str1[MAXLINE]="客户端IP:";
char str2[MAXLINE]="服务器实现者学号:";
char str3[MAXLINE]="当地时间:";
if(argc != 2){
fprintf(stderr,"usage:%s <port>
",argv[0]);
exit(0);
}
port = atoi(argv[1]);
signal(SIGCHLD,sigchld_handler);
listenfd = open_listenfd(port);
while(1){
clientlen = sizeof(clientaddr);
connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);
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);
if(fork() == 0){
close(listenfd);
lt = time(NULL);
local = localtime(<);
strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
send(connfd,sbuf,MAXLINE,0);
close(connfd);
exit(0);
}
close(connfd);
}
}
代码托管
本周结对学习情况
- [20155203](http://www.cnblogs.com/xhwh/p/7822561.html)
- 结对学习内容
课下练习、一起读书、一起研究课下测试。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 | |
第五周 | 200/1500 | 2/11 | 10/100 | |
第六周 | 200/1700 | 2/13 | 10/110 | |
第七周 | 302/2020 | 1/14 | 10/120 | |
第八周 | 892/2912 | 1/14 | 10/130 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
-
计划学习时间:10小时
-
实际学习时间:10小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)