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

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

一、学习笔记——网络编程

1、三种并发方式

构造并发程序的方法有三种:

  • 进程
  • 线程
  • I/O多路复用

进程:用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制。

线程:运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间。

I/O多路复用:应用程序在一个进程的上下文中显式地调度控制流。逻辑流被模型化为状态机。

2、C/S编程模型

客户端和服务器都是进程,C/S编程模型由一个服务器进程和一个或多个客户端进程组成

服务器进程管理某种资源,通过操作这种资源来为它的客户端提供某种服务。基本操作为事务,一个客户端-服务器事务由四步组成:

  • 客户端向服务器发送请求,发起一个事务;

  • 服务器收到请求,操作资源;

  • 服务器给客户端发送一个响应,并等待下一个请求。

  • 客户端收到响应并处理它。

3、线程控制及相关系统调用

在上一次的socket编程中,服务器持续listen,如果有客户端进程请求,服务器父进程就会派生一个子进程来处理新的连接请求。这便存在基于进程的并发编程。

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

二、Linux实现命令——mypwd

1、pwd命令学习

在Linux中使用man命令查看pwd:

实际操作使用pwd命令:

pwd命令的作用是查看当前所在的工作路径。

2、思路

基本原理:

每个目录下都至少有两个内容‘.’和’..’,其中‘.’代表当前目录,’..’代表父目录。每个目录或文件都有对应的i-节点号。

$ ls -1ia(数字1,不是字母l):查看当前目录下的文件名和对应的i-节点号。

伪代码不会写(写出来不规范,可能只有自己看得懂),思路大概是:

  • 查看本目录的i-节点,找到父目录;

  • 进入父目录,输出其i-节点对应的文件夹名;

  • 循环以上过程直到到达根目录;

注:首先找到的目录是较小的子目录,最后才读取到根目录。但是输出是从根目录开始的。

典型的输入输出逆序问题,一般两种解决方案:一是用栈,二是用递归。

这里我使用递归实现。

判断是否抵达根目录

根目录的‘.’和’..’相同,i-节点号相同。

用到的核心函数
  • stat(char* fname, struct stat* bufp);把文件fname的信息复制到bufp所指结构体里(stat结构体包含了文件的信息,在/user/include/sys/stat.h中可以看到struct stat的成员变量。);

  • readdir(DIR* dir_ptr)读取dir_ptr目录的所有文件和目录,返回值是struct dirent结构体;每次调用都会指向下一个文件,遍历完后返回值为NULL;

  • chdir

3、实现mypwd

代码:

///////////////////////////////////////////
//mypwd.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
void mypwd(ino_t this_inode);
void inum_to_name(ino_t inode_to_find,char* namebuf,int buflen);
ino_t get_inode(char* fname);
//返回文件的i节点
ino_t get_inode(char* fname)            
{
    struct stat info;
	if (stat(fname, &info) == -1){
	fprintf( stderr , "Cannot stat ");
	perror(fname);
	exit (1);
	}
	return info.st_ino;
}
void mypwd(ino_t this_inode)
{
    ino_t my_inode;
	char its_name[BUFSIZ];
	//检查本目录是不是根目录
	if (get_inode("..")!=this_inode)                                 
	{
		//进入上级目录
		chdir("..");         
		inum_to_name(this_inode,its_name,BUFSIZ);
		my_inode = get_inode(".");
		mypwd(my_inode);
		printf("/%s",its_name);
	}
}
//找到i节点对应的文件名,并放在字符数组里
void inum_to_name(ino_t inode_to_find,char* namebuf,int buflen)   
{
	DIR* dir_ptr;
	struct dirent* direntp;
	dir_ptr = opendir(".");
	if (dir_ptr == NULL)
	{
		perror(".");
		exit(1);
	}
	//寻找指定i节点的目录,将目录名复制到namebuf中。
	while((direntp = readdir(dir_ptr)) != NULL)
	{
		if(direntp->d_ino == inode_to_find)
		{
		strncpy(namebuf,direntp->d_name,buflen);
		namebuf[buflen-1] = '';
		closedir(dir_ptr);
		return;
		}
	}
	fprintf( stderr , "ERROR while looking for inum %d : NOT FOUND!
",(int)inode_to_find);
	exit (1);
}
int main()
{
	//显示路径
	mypwd(get_inode("."));  
	putchar('
');
	return 0;
}

4、测试mypwd

原文地址:https://www.cnblogs.com/maxeysblog/p/10015303.html