欢迎在评论中提问...
我会边写这个Note边添加Tips...
在OS161中, 所有应用程序在打开, 关闭, 读取, 写入一个文件的时候, 都是通过一个file descriptor [ID]来标识某一个文件的. 需要注意的是, file descriptor [ID]和vnode是完全两个东西.
每个thread都有单独一套file descriptors [ID], 但两个thread的两个不同的file descriptor [ID]如果标识的是同一个文件, 则共用一个vnode.
(这里所说的file descriptors实际上只是一个int, 是代表一个file descriptor的ID, 而实际上file descriptor要保存很多内容. 后边继续)
简单来说, 我们需要给每一个thread都增加一个, 记录所有opened file的机制. 我们暂称之为file table.
file table可以就是个简单的array, 但为了让file table的operation和thread以及syscall相互独立, 减少重复code并减少bug机会, 我强烈建议大家把file table相关的所有operations都写成独立的functions, 放在单独的文件里.
file table其实很简单, 一个array外加一个size_t记录array的长度, 就ok了. (这里说的所有array都是struct array, OS161中自带的kernel array lib)
file descriptor中需要记录以下几个东西,
然后就是操作file table的各种function, 比如
至此基本没有难点 (就类似写个小"class").
之后要把file table添加到thread里, 并且在thread_fork中进行initialization.
这是Assignment在"Implementing file system calls"中特别提到的一点.
在建立一个新的process时候, 不止要initialization一个file table, 而且还要把table的0, 1, 2分别设置成standard input, standard output和standard error, 不然printf就不work哦, 哈哈哈.
注: OS161中stdout和stderr是一样的.
open步骤 1. 创建file descriptor 2. vfs_open打开文件 (获取vnode) 3. 往file descriptor中存需要的数据 4. 把file descriptor加到file table中, 并取得ID 5. return ID给user program
如何用vfs_open打开文件, 请参考runprogram.c
有file descriptor就有vnode...如何用VOP_READ配合vnode和uio读文件, 请参看loadelf.c
注意offset怎么算!!!!!
考验你读code读够不够细致的时候到了...好好读vnode.h(的comment)吧.
Write和Read差在uio的配置, 和用VOP_WRITE.
请细读uio.h(的comment)= =...都是comment有用, code看不懂影响不是很大.
fork, getpid, waitpid, _exit...
注: 按我的理解, OS161所有的thread都是process, 只不过有parent和child之分.
这部分中, PID的管理逻辑是关键, 主要解决几个问题.
和file descriptor类似, PID也需要构建一个table. 区别在于, process table必须是global的! 也就是说, 整个系统只有一个process table.
然后考虑, 我们需要为每个PID/process保存哪些信息, 才能解决上边列举的几个问题.
process table相关的function (仅供参考),
第一个Assignment写完, 对于thread_sleep和thread_wakeup应该都很熟悉了.
两个function都consume一个pointer作为钥匙. 只要sleep的thread和wakeup的thread用的是同一个钥匙, 睡着的所有thread就能被唤醒.
这在implement waitpid和_exit的时候是很实用的.
这估计是这次Assignment中最难的部分.
fork的作用是生成一个和当前thread完全一样的thread. 说具体点就是,
fork system call要点:
thread_fork要点:
md_forkentry要点:
Follow这些要点, 应该可以比较顺利的搞定fork. 但我仍推荐先把fork和md_forkentry的工作原理搞明白, 再开始.
(如果写完了还没明白, 为什么要把md_forkentry pass给thread_fork, 那你绝对是奇葩)
到这里, A2中最难的部分过去了...
runprogram和execv, 我不确定有没有时间在下周一之前总结出来.
这两个大同小异, runprogram写好, execv只是稍微多点东西.
exception handling是打酱油...
大家加油
]]>NoSQL据说就是要break these properties= =`IDK why...
SELECT attribute-expression-list FROM relation-list [ WHERE condition ];
attribute-expression-list:
relation-list:
condition:
AND | TRUE | FALSE | NULL |
TRUE | TRUE | FALSE | NULL |
FALSE | FALSE | FALSE | FALSE |
NULL | NULL | FALSE | NULL |
OR | TRUE | FALSE | NULL |
TRUE | TRUE | TRUE | TRUE |
FALSE | TRUE | FALSE | NULL |
NULL | TRUE | NULL | NULL |
NOT | TRUE | FALSE | NULL |
FALSE | TRUE | NULL |
(Q1 and Q2 must have same attribute-list)
Q1 UNION Q2 => Together all the tuples in Q1 and Q2
Q1 INTERSECT Q2 => Only tuples in both Q1 and Q2
Q1 EXCEPT Q2 => Tuples only in Q1 but not in Q2
ALL关键字: 允许重复
UNION ALL will include twice of duplicate tuples
INTERSECT ALL will include all possible pairs of match tuples, duplication possible
EXCEPT ALL will include all "not in Q2" tuples, duplication possible
SELECT ... ... ORDER BY attribute [DESC/ASC], attribute [DESC/ASC], ......
Note: 如果没有指定Order, return的数据可能是任意顺序
{count, sum, avg, min, max} => Aggregate expressions
Order: Group => Having => Aggregate
Note: 没有被group by指定的attribute不能出现在SELECT的attr-list中, 除非是aggregate
INSERT INTO relation-name [( attribute-list )] VALUE ( value-list );
DELETE FROM relation-name [ WHERE condition ];
UPDATE relation-name SET attribute-assignment-list [ WHERE condition ];
attribute-assignment-list:
CREATE TABLE relation-name ( attribute-name attribute-type [constraints-list], ... )
attribute-type: http://www.w3school.com.cn/sql/sql_datatypes.asp
constraints-list: (Constraints的格式在各种数据库中都不太一样, 就不列举了)
CREATE VIEW view-name AS ( SELECT ... )
从View SELECT的方法和table一样
CREATE TRIGGER trigger-name
AFTER UPDATE OF attribute-list ON relation-name
REFERENCING OLD as instance-name(o) NEW as instance-name(n)
FOR EACH ROW ...
不同database语法不一
]]>