2018-2019-1 20165212 《信息安全系统设计基础》第八周学习总结
一、知识点总结
1、三种并发方式
构造并发程序的方法有三种:
- 进程
- 线程
- I/O多路复用
进程:用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制。
线程:运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。
I/O多路复用:应用程序在一个进程的上下文中显式地调度控制流。逻辑流被模型化为状态机。
2、C/S编程模型
客户端和服务器都是进程,C/S编程模型由一个服务器进程和一个或多个客户端进程组成
服务器进程管理某种资源,通过操作这种资源来为它的客户端提供某种服务。基本操作为事务,一个客户端-服务器事务由四步组成:
- 客户端向服务器发送请求,发起一个事务;
- 服务器收到请求,操作资源;
- 服务器给客户端发送一个响应,并等待下一个请求。
- 客户端收到响应并处理它。
3、线程控制及相关系统调用
socket编程中:线程是运行子进程上下文中的逻辑流
线程与进程的不同:
- 线程的上下文切换要比进程的上下文切换快得多;
- 和一个进程相关的线程组成对等,独立于其他线程创建的线程。
- 主线程和其他线程的区别仅在于它总是进程中第一个运行的线程。
创建线程
- pthread create:创建一个新的线程,在新线程的上下文中运行线程例程f。
- 新线程可以通过pthread _self获得自己的线程ID。
终止线程
- 一个线程的终止方式:当顶层的线程例程返回,线程会隐式地终止;
- pthread_exit:线程显式地终止。
注:如果主线程调用pthread _exit,它会等待所有其他对等线程终止,然后再终止主线程和整个进程。
回收已终止线程的资源
- pthread _join:阻塞,直到线程tid终止,回收已终止线程占用的所有存储器资源。
注:pthread _join只能等待一个指定的线程终止。
分离线程
- 在任何一个时间点上,线程是可结合的或者是分离的。一个可结合的线程能够被其他线程收回其资源和杀死;一个可分离的线程是不能被其他线程回收或杀死的。它的存储器资源在它终止时有系统自动释放。
- 默认情况下,线程被创建成可结合的,为了避免存储器漏洞,每个可集合的线程都应该要么被其他进程显式的回收,要么通过调用pthread _detach被分离。
初始化线程 pthread _once允许初始化与线程例程相关的状态。once _control变量是一个全局或者静态变量,总是被初始化为PTHREAD _ONCE _INIT。
二、通过系统调用实现-pwd命令
步骤:
- 学习 pwd 命令
- 研究实现 pwd 所需要的系统调用
pwd是将当前的文件目录的绝对路径打印出来,所以要找到一个函数可以返回当前文件目录名。所以在命令行中输入 man -k dir | grep get 得到如下的信息:
如上图:getwd正是我们所需要的,通过命令输入: man getwd 得到如下信息:
显然, getwd() 函数功是将当前工作目录的绝对路径复制到数组指针buf中。但是以上代码过于简单,所以按照要求:通过操作目录文件来进行实现 pwd 功能。 思路:
- 1.打开文件目录查看所有目录如果查到当前目录中有两个相同的" ."文件说明已经到了文件根目录,也就是说本目录的i-node与上级目录的i-- node相同。
- 2.否则进入".."文件目录,并且将上一级件目录名记录添加到数组中
- 3.直到符合1的条件为止
具体操作:
- 命令行输入 man -k open | grep dir 找到了符合条件的函数: opendir 。
- 需要读取目录的信息——输入 man -k read | grep dir ,找到符合条件的函数: readdir
- 结束需要关闭文件目录流 man -k close | grep dir ,找到符合条件的函数: readdir
- 通过 man opendir , man readdir,man closedir 等得知各个函数所需的头文件以及函数参数
对于读取文件目录流涉及到一个结构体:
struct dirent{ ino_t d_ino;//文件结点号 off_t d_off; unsigned short d_reclen; unsigined char d_type; char d_name[256];//文件名 }
man -k dir | change 查到fchdir函数: change working directory;
man- k dir 查到chdir作用也是change working directory
比较:
意思是:fchdir用的时候会把当前目录作为打开的文件描述符给出(还不明白)
百度之后查到:fchdir函数传入值是指针fd,函数功能是将当先工作目录改变为fd指的getcwd(gwtcwd函数执行会打印当前文件夹,时间关系,最后打印出来的东西是傻还bzd),但可以肯定的是肯定用的是chdir了。
代码:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> ino_t get_inode(char*); void printpathto(ino_t); void inode_to_name(ino_t,char*,int); int main() { printpathto(get_inode(".")); //print path to here putchar(' '); return 0; } void printpathto(ino_t this_inode) { ino_t my_inode; char its_name[BUFSIZ]; /*如果本目录的i-节点与上级目录不同,即本目录不是根目录*/ if (get_inode("..")!=this_inode) { chdir(".."); //进入上级目录 inode_to_name(this_inode,its_name,BUFSIZ); my_inode = get_inode("."); printpathto(my_inode); printf("/%s",its_name); } } void inode_to_name(ino_t inode_to_find,char* namebuf,int buflen) //找到i-节点对应的文件名,并放在字符数组里 { DIR* dir_ptr; struct dirent* direntp; dir_ptr = opendir("."); if (dir_ptr == NULL) { perror("."); exit(1); } /*上面是打开一个目录流,然后下面是通过目录流读取来查找当前目录的与要找的i-node相对应的文件名,之后关闭目录流*/ while((direntp = readdir(dir_ptr)) != NULL) { if(direntp->d_ino == inode_to_find) { strncpy(namebuf,direntp->d_name,buflen); namebuf[buflen-1] = '