|
|
它是用来分析命令行参数的函数。参数optstring 则代表欲处理的选项字符串。
- 字母后没有符号: 不带值的参数,定义即参数本身
- 字母后带一个冒号: 必须带值,值被全域变量optarg指向。
- 字母后带两个冒号: 可选值的参数,参数可加可不加。
getopt()每次调用会逐次返回命令行传入的参数,当没有参数的最后一次调用会返回-1。
参数返回的是字符串的,有些需要转化为整形,可以用下面函数.
|
|
它是用来分析命令行参数的函数。参数optstring 则代表欲处理的选项字符串。
getopt()每次调用会逐次返回命令行传入的参数,当没有参数的最后一次调用会返回-1。
参数返回的是字符串的,有些需要转化为整形,可以用下面函数.
交换处理: 内存容量不足以容纳整个程序的代码和数据。所以需要定期进行交换处理。
sched(); //用来定期寻找交换处理对象的进程,也被称为swapper
sched() 从proc[]中寻找满足以下条件的进程作为交换处理的对象。
如果换入时内存不足,需要找满足一下条件的进程换出
mess:
spl6() //将处理器优先级设置为6,防止发生中断。
代码段,用text结构体表示
代码段在内存中只读,如果某个程序有多个进程,共享代码段。当内存中没有进程用代码段了,内存自动释放, 交换空间和内存没有进程使用代码段,代码段在交换空间中释放。
内核用map管理内存和交换空间
int coremap[CMAPSIZ]; //以64字节为单位管理
int swapmap[SWAPSIZ]; //以512字节为单位管理
获取未使用的区域采用了First Fit
数组尾部,有一个长度为0的元素,充当哨兵
|
|
C语言中如果参数个数不定,可以用省略号传参
printf 也是用了这种传参方式。
函数传参的时候用到了栈的数据结构,参数从右往左一个一个入栈。所以理论上,知道一个参数的类型和其中一个的地址,就可以知道所有参数。
|
|
可以看一个简单printf的例子
一段时间没写C++,把C++迭代器和java的引用搞混了。
|
|
上述的代码最后it1 加之后it2还是vec.begin()
it2和it1是独立的,这里不和java的引用一样。
使用的时候要把秘钥放到github网站上
克隆一个仓库
添加文件
本地提交改动
推送到master
把仓库连接到远程服务器
查看git状态
版本回退
branch
update and merge
tag
autotools是一系列工具,可以用来制作makefile
其中包括了aclocal,autoscan,autoconf,autoheader,automake
流程
1.运行autoscan.
它会搜索源文件以寻找一般移植性的问题,并创建一个文件”configure.scan”
configure.scan为configure.in的原形文件。
2.修改configure.scan为configure.in,按照描述填上配置
下面是单hello文件的配置。与原始文件相比加上了AM_INIT_AUTOMAKE()和AC_CONFIG_FILES()
|
|
3.执行aclocal,生成”aclocal.m4”,主要功能是处理本地宏定义
4.执行autoconf,生成configure可执行文件
5.执行autoheader,负责生成config.h.in,复制用户附加的符号定义
6.编写makefile.am
|
|
7.执行automake,把makefile.am转换成makefile.in.
automake -a(或automake –adding-missing),可以让automake自动添加一些必须的脚本文件。
8.执行./configure,生成makefile
9.之后就直接可以make,make install,make clean之类的了。如果想要打包为压缩文档发布,直接运行make dist生成tar.gz压缩文件。
《30天自制操作系统》差不多都过了一遍。感觉操作系统和一般程序的最大的区别是可以随意操作和控制内存。而作为操作系统,最重要的是兼容性和稳定性。稳定的最基本的条件就是安全。所以操作系统作为最灵活的“程序”必须在安全方面做好工作。《30天自制操作系统》这本书上也讲了很多关于保护操作系统的知识,让我记忆深刻。下面就来总结一番。
保护操作系统是一项工程量十分巨大的活,有时候一个死角就能够然操作系统运行错误。所以要想保护操作系统,必须对操作系统的运行的每个流程都十分清楚,这样才能够找到操作系统的弱点,并做好防护措施。下面就来回顾一下操作系统的运行流程以及涉及的相关代码。
1.BIOS找到启动区,执行启动区的代码。这段代码所在文件是ipl10.nas,是用汇编写的,引导区只有512字节,不足以存放操作系统,这段代码的主要作用就是设定分区格式,把操作系统读入内存,然后跳入到操作系统核心代码。说简单一点就是引导操作系统。
2.启动区之后直接跳入HariMari函数开始执行。相关代码在bootpack.c。这部分代码主要是初始化键盘、鼠标等硬件设备设备,初始化GDT、IDT、PIC,开放中断,初始化内存、初始化任务并运行,然后进入到了一个循环,在这个循环里面接收键盘和鼠标的数据,并控制数据的发送。
3.操作系统会启动一个终端。相关代码在console.c中。终端是当前的操作系统最重要的交互工具。主要功能是执行相关命令和外部程序。如果当前选中终端,输入字符在HariMari中被接收之后,会发送到终端做相关的显示,如果发送回车键之后,终端会判断是命令还是程序,并执行。
4.如果执行的是外部程序,则操作系统则会跳到程序的主函数执行其代码。为了程序的方便,程序可以调用操作系统所提供的公开API。
分析上面的内容。前三个部分是操作系统所提供的服务。这些部分是不能够被外部程序所更改的,只需要给操作系统关键部分文件加上一定的修改权限就可以了。比如在win7操作系统上,不能够删除系统关键文件,这应该是一个道理。这部分代码是设计和编写操作系统的人编写的,只要这部分代码稳定,能够保证运行正常功能不会出错就可以了。
第四个部分的代码是可以由其它程序员编写的,所以这部分代码可能会存在bug,或者是恶意代码,如果没有做好一定的防护,操作系统可能会崩溃。
下面再来看一下外部文件被操作系统调用的流程。
用户通过键盘向电脑输入相关外部文件名字,然后回车。HariMari函数接收到键盘数据,发送给终端,终端判断输入是否是命令,如果不是命令,则查找是否存在该文件,如果存在文件则通过file_loadfile载入内存,注册gdt,然后跳转执行。
现在假设操作系统没有任何防备,看看应用程序能够做些什么来破坏操作系统。
1.语言直接修改内存数值。
这是C语言的特性,在操作系统没限制的条件下,可以通过指针修改任意内存的值。
这个本来应该是操作系统的权力。在实现操作系统的时候可以通过在一些内存中写入来保存数据,把数据当全局变量来用。这个在之前的内容中也用到过。但是如果是外部的软件,当然不可能给予它这么大的权限,所以需要把所有软件中的非法内存操作给禁止。
解决方法:专门给应用程序分配数据段,限制应用程序修改的数据范围。如果应用程序需要调用系统函数,则在执行系统函数之前先把段地址切换到操作系统所在段再执行。执行好之后回到应用程序段,切换段以及执行api的操作由操作系统提供,只需要再对应用程序对api给的参数进行合法性校检就可以了。
2.用汇编写第三方程序,忽略操作系统指定的数据段。
这个是上面的解决方法的漏洞。c语言编译之后会用系统提供的段,但是汇编更强大,可以自己选定段进行数据修改。
解决方法:让应用程序无法访问操作系统的段。在软件的数据段和代码段上的访问权限加上0x60,这样可以将段设置为应用程序用。该段中的代码如果要访问操作系统所在段代码是非法的。这个0x60是x86架构中提供的,在现在的操作系统中只需要设定好久行了,不需要编写额外的代码。处于好奇,我去查了一下arm,里面有一个MMU,也可以设定访问权限,功能与x86类似。看来这部分内容在操作系统中至关重要,在处理器架构上面就已经把这个问题考虑清楚了。
申明段为应用程序段之后还有其它的一系列好处,比如应用程序不能够直接执行IN和OUT指令,这样可以防止应用程序更改定时器的周期,让定时器运行缓慢。除了这个,在应用程序中,也不能够执行CLI、STI和HLT之类的指令,这些指令在操作系统看来都是危险的,所以0x60的设置极大地提高了系统的安全性。
|
|
3.破坏应用程序所在段中的数据。
应用程序不能够对操作系统的段进行修改,所以篡改操作系统是没用的了。但是可以篡改应用程序所在段的内容,让其它应用程序无法正常运行。对于CPU来说,应用程序访问应用程序所在段应该是理所当然的。但是这的确西药改进,如果操作系统中的应用程序很容易受到其它应用程序的干扰,而操作系统对此也不能够做些什么,那这个操作系统也是失败的操作系统。
解决方法:由gdt可以得到一些启示,可以动态修改gdt设置,把正在运行的程序gdt设置为应用程序段,把不在运行的程序设置为操作系统段。这样的话如果运行的应用程序想要破坏其它应用程序,那也只能够破坏和它同时运行的应用程序,大大降低了危害。但是这样有很多缺点,比如说一个程序就要用好几个gdt,而且每次更改起来也比较麻烦。
其实对于这个问题,CPU已经准备好了解决的方案。就是LDT。我们知道,GDT是全局段描述符表,而LDT则是局部段描述符表。每个LDT都是互相独立的,不能够访问各自的资源。所以只需要把应用程序设置在LDT中,这样其它应用程序就不能够访问该应用程序的段,保证了数据的安全。设定LDT也很简单,只需要在任务的tss中给成员变量ldtr赋相应值就可以了。
|
|
最后来谈一下对一些破坏性程序的处理。
作为一个可用的操作系统,如果应用程序具有破坏性,那么运行之后就应该做到适当的提示,以及能够强制关闭应用程序,不要让它继续占用内存和CPU。这样操作系统才能够更加稳定。
对于一些恶意代码,比如在应用程序中修改操作系统段的数据,或者在应用程序中执行STI等操作,由于我之前设定过0x60的段权限,应用程序会自动产生0x0d中断(异常中断),在这个中断中,我可以写一些代码来关闭应用程序做好善后工作。
|
|
现在再来回顾一下操作系统,只要其内部稳定,基本上就很难被外部程序给干扰。因为操作系统和程序已经隔离。应用程序不能够破坏操作系统数据,如果要高权限操作,应用程序可以调用操作系统公开的api来完成。同时应用程序和应用程序间也独立,互不干扰。这样的操作系统才能经受住考验。
redis使用一个sds来表示一个字符串
###不用C字符串的原因
不停地重分配内存性能会损失很多,redis的sds实现了空间预分配和惰性空间释放两种优化策略
预分配
惰性空间释放
|
|
最近学了一下Flask,感觉这类东西使用起来还是差不多的。
以前感觉python应用部署起来比较麻烦,其实部署过之后还是蛮简单的。
virtualenv真是神器,可以创建独立的python环境。
其实在没接触到这个之前一直是直接装在原始环境中的,pip还老是遇到permission问题,要sudo.
最近把windows上的virtualbox更新了一下,原来用的是绿色版,但是那个网络的服务老是报异常,需要卸载再安装一遍。比较麻烦所以索性换掉了。virtualbox下mount的地方使用virtualenv会遇到permission error的问题,应该是virtualbox的bug.
virtualbox里面的debian感觉x-windows不怎么需要,所以直接取消启动了,为了粘贴方便,迫不得已装了一个openbox.
pip在装一些软件的时候会少一些东西,一般装上python-dev和mysql-dev(好像不叫这个名字)就可以了
还有些pip下载慢,需要代理,可以用proxychains4,不能够直接apt-get装,装了好像有问题,可以直接clone https://github.com/rofl0r/proxychains-ng 编译安装。
赞一下aptitude很好用啊。可以给你几个选项来解决依赖问题。十分方便。
要在windows上用virtualbox实在是有点麻烦,只是现在有个项目还要用到myeclipse和vc++,不然就可以完全转到linux下工作了。
linux查看端口占用信息
mosh这个软件很好用,没有代理的情况下访问vps速度飞快。
但是windows上就只有Cygwin和chrome上有。
Cygwin不太想装。chrome上面有时候会出现载入一个module时卡住的问题,google了一下好像是bug,暂时无解。希望能改善。
使用mosh一定要两边的字符集一样,不然会报错误。