系统调用

socket之命名、监听、连接、关闭

只谈情不闲聊 提交于 2019-12-19 01:30:24
命名socket   创建socket时,指定了地址族,但是并未指定使用该地址族中的那个具体socket地址。将一个socket与socket地址绑定称为给socket命名。在服务器程序中,我们通常要命名socket,因为只有命名后客户端才能知道该如何连接它。客户端通常不需要命名socket,而是采用匿名方式,即使用操作系统自动分配的socket地址。   命名的socket的系统调用是bind,定义如下:   bind将my_addr所指的socket地址分配给未命名的sockfd文件描述符,addrlen参数指定该socket地址的长度。   bind成功时返回0,失败则返回-1并设置errno:(常见的两种errno) 监听socket   socket被命名之后,还不能马上接收客户连接,我们需要使用如下系统调用来创建一个监听队列以存放待处理的客户连接:   sockfd参数指定被监听的socket。backlog参数提示内核监听队列的最大长度。监听队列的长度如果超过backlog,服务器将不受理新的客户连接,客户端也将受到ECONNREFUSED错误信息。(在内核版本2.2之前的Linux中,backlog参数是指所有处于半连接状态和完全连接状态的socket的上限。在此之后,他只表示处于完全连接状态的socket上限,处于半连接状态的socket的上限则由/proc

系统调用

痞子三分冷 提交于 2019-12-18 22:57:29
由前2篇文章做基础,现在可以理解系统调用了。 用户空间栈&系统空间栈 中断&异常 系统调用定义 系统调用是内核提供的一系列强大的函数。它们在内核中实现,然后通过一定的方式(X86是软中断,也即门陷入)呈现给用户,是用户程序与内核交互的接口。 注意,我们在程序中用调用read、write函数时,这些不是系统调用函数,而是glibc库包装后,进行一些处理,然后再调用系统调用。如果想在程序中直接调用 的 话,需要调用_syscall()函数。 上下文(context) 上下文简单说来就是一个环境,相对于进程而言,就是进程执行时的环境。具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。 一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文。 用户级上下文: 正文、数据、用户堆栈以及共享存储区; 寄存器上下文: 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP); 系统级上下文: 进程控制块task_struct、内存管理信息(mm_struct、vm_area_struct、pgd、pte)、内核栈。 当发生进程调度时,进行进程切换就是上下文切换(context switch).操作系统必须对上面提到的全部信息进行切换,新调度的进程才能运行。而系统调用进行的模式 切换(mode switch)

Janus工具介绍

核能气质少年 提交于 2019-12-18 09:59:59
Janus工具介绍 记录时间: 2019.12.6 。这一次偷懒就直接对着上课写的PPT讲了,仅供参考。 github: https://github.com/sslab-gatech/janus https://taesoo.kim/pubs/2019/xu:janus-slides.pdf 1.硬编码:文件路径来生成随机的系统调用,即类似于path=”/bin/sh”的类型,将数据直接嵌入到程序或其他可执行对象的源代码。 问题:文件操作是一种上下文相关的工作负载(workload),映像与执行的文件操作之间存在依赖关系。而这种 硬编码不能生成有意义的文件操作序列,并且覆盖文件系统的深层代码路径 。 2.随着文件系统与操作系统的复杂性不断增加,fuzz困难度上升的情况下,再现已发现的bug依赖于VM,QEMU或Linux用户模式(UML)会产生 巨大的时间开销 。 常见的fuzzer测试依赖于最小完整性检查的 回归测试 。这是一种修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误的方法。而重用实例则虽然能减少重新加载的开销,但会进一步导致 操作系统状态不稳定 ,最终导致不稳定的执行与不可恢复的bug。同时由于前面积累了许多的变化,也难 以确定是哪一个调用真正地造成了崩溃 。除却时间,空间开销也是很重要的一点。由于文件系统的庞大性, 大量涉及IO操作

golang goroutine的调度

℡╲_俬逩灬. 提交于 2019-12-18 09:12:22
golang goroutine的调度 1、什么是协程? 协程是一种用户态的轻量级线程。 2、进程、线程、协程的关系和区别: * 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。 * 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。 * 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。 * 协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能。 * 执行协程只需要极少的栈内存(大概是4~5KB),默认情况下,线程栈的大小为1MB。 goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行。 runtime。GOMAXPROCS(runtime。NumCPU()) // go version>=1.5的时候,GOMAXPROCS的默认值就是go程序启动时可见的操作系统认为的CPU个数。 注意:在go程序中使用的操作系统线程数量包括:正服务于cgo calls的线程,阻塞于操作系统calls的线程,所以go程序中使用的操作系统线程数量可能大于GOMAXPROCS的值。 3、调度 要理解协程的实现,首先需要了解go中的三个非常重要的概念,它们分别是G(goroutine)、M

进程控制实验--fork()

三世轮回 提交于 2019-12-16 22:51:20
二 进程的控制 实验目的 1、掌握进程另外的创建方法 2、熟悉进程的睡眠、同步、撤消等进程控制方法 实验内容 1、用fork( )创建一个进程,再调用exec( )用新的程序替换该子进程的内容 2、利用wait( )来控制进程执行顺序 实验指导 一、所涉及的系统调用 在UNIX/LINUX中fork( )是一个非常有用的系统调用,但在UNIX/LINUX中建立进程除了fork( )之外,也可用与fork( ) 配合使用的exec( )。 1、exec( )系列 系 统调用exec( )系列,也可用于新程序的运行。fork( )只是将父进程的用户级上下文拷贝到新进程中,而exec( )系列可以将一个可执行的二进制文件覆盖在新进程的用户级上下文的存储空间上,以更改新进程的用户级上下文。exec( )系列中的系统调用都完成相同的功能,它们把一个新程序装入内存,来改变调用进程的执行代码,从而形成新进程。如果exec( )调用成功,调用进程将被覆盖,然后从新程序的入口开始执行,这样就产生了一个新进程,新进程的进程标识符id 与调用进程相同。 exec( )没有建立一个与调用进程并发的子进程,而是用新进程取代了原来进程。所以exec( )调用成功后,没有任何数据返回,这与fork( )不同。exec( )系列系统调用在UNIX系统库unistd.h中,共有execl、execlp、execle

【计算机笔记】操作系统概述

核能气质少年 提交于 2019-12-16 22:06:31
基本特征 1. 并发 2. 共享 3. 虚拟 4. 异步 基本功能 1. 进程管理 2. 内存管理 3. 文件管理 4. 设备管理 系统调用 大内核和微内核 1. 大内核 2. 微内核 中断分类 1. 外中断 2. 异常 3. 陷入 基本特征 1. 并发 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。 并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。 操作系统通过引入进程和线程,使得程序能够并发运行。 2. 共享 共享是指系统中的资源可以被多个并发进程共同使用。 有两种共享方式:互斥共享和同时共享。 互斥共享的资源称为临界资源,例如打印机等,在同一时刻只允许一个进程访问,需要用同步机制来实现互斥访问。 3. 虚拟 虚拟技术把一个物理实体转换为多个逻辑实体。 主要有两种虚拟技术:时(时间)分复用技术和空(空间)分复用技术。 多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。 虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。 4. 异步 异步指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。

实验1-进程控制

扶醉桌前 提交于 2019-12-16 20:11:46
编写程序,演示多进程并发执行和进程软中断、管道通信。 (1) 父进程使用系统调用pipe( )建立一个管道,然后使用系统调用fork()创建两个子进程,子进程1和子进程2; (2) 子进程1每隔1秒通过管道向子进程2发送数据: I send you x times. (x初值为1,每次发送后做加一操作) (3) 子进程2从管道读出信息,并显示在屏幕上; (4) 父进程用系统调用signal()捕捉来自键盘的中断信号(即按Ctrl+C键);当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止: Child Process l is Killed by Parent! Child Process 2 is Killed by Parent! (5) 父进程等待两个子进程终止后,释放管道并输出如下的信息后终止 Parent Process is Killed! 源码下载 (1)思路:   按照实验内容,我们需要用父进程创建两个子进程,从而实现子进程之间通过管道(除此之外,还有mmap,fifo通信方式)来实现进程间通信。所以我们需要首先创建出两个子进程(这里注意fork函数使用的时候,避免子进程再创建出新的子子进程的问题,这样可能会导致整个程序退出的时候出现孤儿进程)。具体的进程通信步骤会在下面说明,还有就是Linux下信号的使用