Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
ca568c2a
提交
ca568c2a
3月 27, 2012
创建
作者:
Silas Boyd-Wickizer
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'scale-amd64' of
git+ssh://amsterdam.csail.mit.edu/home/am0/6.828/xv6
into scale-amd64
上级
a9759582
69f0e679
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
525 行增加
和
2 行删除
+525
-2
Makefrag
bin/Makefrag
+1
-0
nsh.cc
bin/nsh.cc
+494
-0
fcntl.h
include/fcntl.h
+1
-0
sysfile.cc
kernel/sysfile.cc
+29
-2
没有找到文件。
bin/Makefrag
浏览文件 @
ca568c2a
...
...
@@ -16,6 +16,7 @@ UPROGS= \
mkdir \
mktree \
sh \
nsh \
halt \
time \
sleep \
...
...
bin/nsh.cc
0 → 100644
浏览文件 @
ca568c2a
// Shell.
#include "types.h"
#include "user.h"
#include "fcntl.h"
// Parsed command representation
#define EXEC 1
#define REDIR 2
#define PIPE 3
#define LIST 4
#define BACK 5
#define MAXARGS 10
struct
cmd
{
int
type
;
};
struct
execcmd
{
int
type
;
const
char
*
argv
[
MAXARGS
];
char
*
eargv
[
MAXARGS
];
};
struct
redircmd
{
int
type
;
struct
cmd
*
cmd
;
char
*
file
;
char
*
efile
;
int
mode
;
int
fd
;
};
struct
pipecmd
{
int
type
;
struct
cmd
*
left
;
struct
cmd
*
right
;
};
struct
listcmd
{
int
type
;
struct
cmd
*
left
;
struct
cmd
*
right
;
};
struct
backcmd
{
int
type
;
struct
cmd
*
cmd
;
};
int
fork1
(
void
);
// Fork but panics on failure.
void
panic
(
const
char
*
);
struct
cmd
*
parsecmd
(
char
*
);
// Execute cmd. Never returns.
void
runcmd
(
struct
cmd
*
cmd
)
{
int
p
[
2
];
struct
backcmd
*
bcmd
;
struct
execcmd
*
ecmd
;
struct
listcmd
*
lcmd
;
struct
pipecmd
*
pcmd
;
struct
redircmd
*
rcmd
;
if
(
cmd
==
0
)
exit
();
switch
(
cmd
->
type
){
default:
panic
(
"runcmd"
);
case
EXEC
:
ecmd
=
(
struct
execcmd
*
)
cmd
;
if
(
ecmd
->
argv
[
0
]
==
0
)
exit
();
exec
(
ecmd
->
argv
[
0
],
ecmd
->
argv
);
fprintf
(
2
,
"exec %s failed
\n
"
,
ecmd
->
argv
[
0
]);
break
;
case
REDIR
:
rcmd
=
(
struct
redircmd
*
)
cmd
;
close
(
rcmd
->
fd
);
if
(
open
(
rcmd
->
file
,
rcmd
->
mode
)
<
0
){
fprintf
(
2
,
"open %s failed
\n
"
,
rcmd
->
file
);
exit
();
}
runcmd
(
rcmd
->
cmd
);
break
;
case
LIST
:
lcmd
=
(
struct
listcmd
*
)
cmd
;
if
(
fork1
()
==
0
)
runcmd
(
lcmd
->
left
);
wait
();
runcmd
(
lcmd
->
right
);
break
;
case
PIPE
:
pcmd
=
(
struct
pipecmd
*
)
cmd
;
if
(
pipe
(
p
)
<
0
)
panic
(
"pipe"
);
if
(
fork1
()
==
0
){
close
(
1
);
dup
(
p
[
1
]);
close
(
p
[
0
]);
close
(
p
[
1
]);
runcmd
(
pcmd
->
left
);
}
if
(
fork1
()
==
0
){
close
(
0
);
dup
(
p
[
0
]);
close
(
p
[
0
]);
close
(
p
[
1
]);
runcmd
(
pcmd
->
right
);
}
close
(
p
[
0
]);
close
(
p
[
1
]);
wait
();
wait
();
break
;
case
BACK
:
bcmd
=
(
struct
backcmd
*
)
cmd
;
if
(
fork1
()
==
0
)
runcmd
(
bcmd
->
cmd
);
break
;
}
exit
();
}
int
getcmd
(
char
*
buf
,
int
nbuf
)
{
fprintf
(
2
,
"$ "
);
memset
(
buf
,
0
,
nbuf
);
gets
(
buf
,
nbuf
);
if
(
buf
[
0
]
==
0
)
// EOF
return
-
1
;
return
0
;
}
int
main
(
void
)
{
static
char
buf
[
100
];
int
fd
;
// Assumes three file descriptors open.
while
((
fd
=
open
(
"console"
,
O_RDWR
))
>=
0
){
if
(
fd
>=
3
){
close
(
fd
);
break
;
}
}
// Read and run input commands.
while
(
getcmd
(
buf
,
sizeof
(
buf
))
>=
0
){
if
(
buf
[
0
]
==
'c'
&&
buf
[
1
]
==
'd'
&&
buf
[
2
]
==
' '
){
// Clumsy but will have to do for now.
// Chdir has no effect on the parent if run in the child.
buf
[
strlen
(
buf
)
-
1
]
=
0
;
// chop \n
if
(
chdir
(
buf
+
3
)
<
0
)
fprintf
(
2
,
"cannot cd %s
\n
"
,
buf
+
3
);
continue
;
}
if
(
fork1
()
==
0
)
runcmd
(
parsecmd
(
buf
));
wait
();
}
exit
();
}
void
panic
(
const
char
*
s
)
{
fprintf
(
2
,
"%s
\n
"
,
s
);
exit
();
}
int
fork1
(
void
)
{
int
pid
;
pid
=
fork
(
0
);
if
(
pid
==
-
1
)
panic
(
"fork"
);
return
pid
;
}
//PAGEBREAK!
// Constructors
struct
cmd
*
execcmd
(
void
)
{
struct
execcmd
*
cmd
;
cmd
=
(
struct
execcmd
*
)
malloc
(
sizeof
(
*
cmd
));
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
type
=
EXEC
;
return
(
struct
cmd
*
)
cmd
;
}
struct
cmd
*
redircmd
(
struct
cmd
*
subcmd
,
char
*
file
,
char
*
efile
,
int
mode
,
int
fd
)
{
struct
redircmd
*
cmd
;
cmd
=
(
struct
redircmd
*
)
malloc
(
sizeof
(
*
cmd
));
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
type
=
REDIR
;
cmd
->
cmd
=
subcmd
;
cmd
->
file
=
file
;
cmd
->
efile
=
efile
;
cmd
->
mode
=
mode
;
cmd
->
fd
=
fd
;
return
(
struct
cmd
*
)
cmd
;
}
struct
cmd
*
pipecmd
(
struct
cmd
*
left
,
struct
cmd
*
right
)
{
struct
pipecmd
*
cmd
;
cmd
=
(
struct
pipecmd
*
)
malloc
(
sizeof
(
*
cmd
));
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
type
=
PIPE
;
cmd
->
left
=
left
;
cmd
->
right
=
right
;
return
(
struct
cmd
*
)
cmd
;
}
struct
cmd
*
listcmd
(
struct
cmd
*
left
,
struct
cmd
*
right
)
{
struct
listcmd
*
cmd
;
cmd
=
(
struct
listcmd
*
)
malloc
(
sizeof
(
*
cmd
));
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
type
=
LIST
;
cmd
->
left
=
left
;
cmd
->
right
=
right
;
return
(
struct
cmd
*
)
cmd
;
}
struct
cmd
*
backcmd
(
struct
cmd
*
subcmd
)
{
struct
backcmd
*
cmd
;
cmd
=
(
struct
backcmd
*
)
malloc
(
sizeof
(
*
cmd
));
memset
(
cmd
,
0
,
sizeof
(
*
cmd
));
cmd
->
type
=
BACK
;
cmd
->
cmd
=
subcmd
;
return
(
struct
cmd
*
)
cmd
;
}
//PAGEBREAK!
// Parsing
char
whitespace
[]
=
"
\t\r\n\v
"
;
char
symbols
[]
=
"<|>&;()"
;
int
gettoken
(
char
**
ps
,
char
*
es
,
char
**
q
,
char
**
eq
)
{
char
*
s
;
int
ret
;
s
=
*
ps
;
while
(
s
<
es
&&
strchr
(
whitespace
,
*
s
))
s
++
;
if
(
q
)
*
q
=
s
;
ret
=
*
s
;
switch
(
*
s
){
case
0
:
break
;
case
'|'
:
case
'('
:
case
')'
:
case
';'
:
case
'&'
:
case
'<'
:
s
++
;
break
;
case
'>'
:
s
++
;
if
(
*
s
==
'>'
){
ret
=
'+'
;
s
++
;
}
break
;
default:
ret
=
'a'
;
while
(
s
<
es
&&
!
strchr
(
whitespace
,
*
s
)
&&
!
strchr
(
symbols
,
*
s
))
s
++
;
break
;
}
if
(
eq
)
*
eq
=
s
;
while
(
s
<
es
&&
strchr
(
whitespace
,
*
s
))
s
++
;
*
ps
=
s
;
return
ret
;
}
int
peek
(
char
**
ps
,
char
*
es
,
const
char
*
toks
)
{
char
*
s
;
s
=
*
ps
;
while
(
s
<
es
&&
strchr
(
whitespace
,
*
s
))
s
++
;
*
ps
=
s
;
return
*
s
&&
strchr
(
toks
,
*
s
);
}
struct
cmd
*
parseline
(
char
**
,
char
*
);
struct
cmd
*
parsepipe
(
char
**
,
char
*
);
struct
cmd
*
parseexec
(
char
**
,
char
*
);
struct
cmd
*
nulterminate
(
struct
cmd
*
);
struct
cmd
*
parsecmd
(
char
*
s
)
{
char
*
es
;
struct
cmd
*
cmd
;
es
=
s
+
strlen
(
s
);
cmd
=
parseline
(
&
s
,
es
);
peek
(
&
s
,
es
,
""
);
if
(
s
!=
es
){
fprintf
(
2
,
"leftovers: %s
\n
"
,
s
);
panic
(
"syntax"
);
}
nulterminate
(
cmd
);
return
cmd
;
}
struct
cmd
*
parseline
(
char
**
ps
,
char
*
es
)
{
struct
cmd
*
cmd
;
cmd
=
parsepipe
(
ps
,
es
);
while
(
peek
(
ps
,
es
,
"&"
)){
gettoken
(
ps
,
es
,
0
,
0
);
cmd
=
backcmd
(
cmd
);
}
if
(
peek
(
ps
,
es
,
";"
)){
gettoken
(
ps
,
es
,
0
,
0
);
cmd
=
listcmd
(
cmd
,
parseline
(
ps
,
es
));
}
return
cmd
;
}
struct
cmd
*
parsepipe
(
char
**
ps
,
char
*
es
)
{
struct
cmd
*
cmd
;
cmd
=
parseexec
(
ps
,
es
);
if
(
peek
(
ps
,
es
,
"|"
)){
gettoken
(
ps
,
es
,
0
,
0
);
cmd
=
pipecmd
(
cmd
,
parsepipe
(
ps
,
es
));
}
return
cmd
;
}
struct
cmd
*
parseredirs
(
struct
cmd
*
cmd
,
char
**
ps
,
char
*
es
)
{
int
tok
;
char
*
q
,
*
eq
;
while
(
peek
(
ps
,
es
,
"<>"
)){
tok
=
gettoken
(
ps
,
es
,
0
,
0
);
if
(
gettoken
(
ps
,
es
,
&
q
,
&
eq
)
!=
'a'
)
panic
(
"missing file for redirection"
);
switch
(
tok
){
case
'<'
:
cmd
=
redircmd
(
cmd
,
q
,
eq
,
O_RDONLY
|
O_WAIT
,
0
);
break
;
case
'>'
:
cmd
=
redircmd
(
cmd
,
q
,
eq
,
O_WRONLY
|
O_CREATE
|
O_WAIT
,
1
);
break
;
case
'+'
:
// >>
cmd
=
redircmd
(
cmd
,
q
,
eq
,
O_WRONLY
|
O_CREATE
|
O_WAIT
,
1
);
break
;
}
}
return
cmd
;
}
struct
cmd
*
parseblock
(
char
**
ps
,
char
*
es
)
{
struct
cmd
*
cmd
;
if
(
!
peek
(
ps
,
es
,
"("
))
panic
(
"parseblock"
);
gettoken
(
ps
,
es
,
0
,
0
);
cmd
=
parseline
(
ps
,
es
);
if
(
!
peek
(
ps
,
es
,
")"
))
panic
(
"syntax - missing )"
);
gettoken
(
ps
,
es
,
0
,
0
);
cmd
=
parseredirs
(
cmd
,
ps
,
es
);
return
cmd
;
}
struct
cmd
*
parseexec
(
char
**
ps
,
char
*
es
)
{
char
*
q
,
*
eq
;
int
tok
,
argc
;
struct
execcmd
*
cmd
;
struct
cmd
*
ret
;
if
(
peek
(
ps
,
es
,
"("
))
return
parseblock
(
ps
,
es
);
ret
=
execcmd
();
cmd
=
(
struct
execcmd
*
)
ret
;
argc
=
0
;
ret
=
parseredirs
(
ret
,
ps
,
es
);
while
(
!
peek
(
ps
,
es
,
"|)&;"
)){
if
((
tok
=
gettoken
(
ps
,
es
,
&
q
,
&
eq
))
==
0
)
break
;
if
(
tok
!=
'a'
)
panic
(
"syntax"
);
cmd
->
argv
[
argc
]
=
q
;
cmd
->
eargv
[
argc
]
=
eq
;
argc
++
;
if
(
argc
>=
MAXARGS
)
panic
(
"too many args"
);
ret
=
parseredirs
(
ret
,
ps
,
es
);
}
cmd
->
argv
[
argc
]
=
0
;
cmd
->
eargv
[
argc
]
=
0
;
return
ret
;
}
// NUL-terminate all the counted strings.
struct
cmd
*
nulterminate
(
struct
cmd
*
cmd
)
{
int
i
;
struct
backcmd
*
bcmd
;
struct
execcmd
*
ecmd
;
struct
listcmd
*
lcmd
;
struct
pipecmd
*
pcmd
;
struct
redircmd
*
rcmd
;
if
(
cmd
==
0
)
return
0
;
switch
(
cmd
->
type
){
case
EXEC
:
ecmd
=
(
struct
execcmd
*
)
cmd
;
for
(
i
=
0
;
ecmd
->
argv
[
i
];
i
++
)
*
ecmd
->
eargv
[
i
]
=
0
;
break
;
case
REDIR
:
rcmd
=
(
struct
redircmd
*
)
cmd
;
nulterminate
(
rcmd
->
cmd
);
*
rcmd
->
efile
=
0
;
break
;
case
PIPE
:
pcmd
=
(
struct
pipecmd
*
)
cmd
;
nulterminate
(
pcmd
->
left
);
nulterminate
(
pcmd
->
right
);
break
;
case
LIST
:
lcmd
=
(
struct
listcmd
*
)
cmd
;
nulterminate
(
lcmd
->
left
);
nulterminate
(
lcmd
->
right
);
break
;
case
BACK
:
bcmd
=
(
struct
backcmd
*
)
cmd
;
nulterminate
(
bcmd
->
cmd
);
break
;
}
return
cmd
;
}
include/fcntl.h
浏览文件 @
ca568c2a
...
...
@@ -2,6 +2,7 @@
#define O_WRONLY 0x001
#define O_RDWR 0x002
#define O_CREATE 0x200
#define O_WAIT 0x400 // open waits for create, read for write
#define AT_FDCWD -100
...
...
kernel/sysfile.cc
浏览文件 @
ca568c2a
...
...
@@ -295,14 +295,41 @@ sys_openat(int dirfd, const char *path, int omode)
if
(
omode
&
O_CREATE
){
if
((
ip
=
create
(
cwd
,
path
,
T_FILE
,
0
,
0
))
==
0
)
return
-
1
;
if
(
omode
&
O_WAIT
){
// XXX wake up any open(..., O_WAIT).
// there's a race here that's hard to fix because
// of how non-locking create() is.
char
dummy
[
DIRSIZ
];
struct
inode
*
pip
=
nameiparent
(
cwd
,
path
,
dummy
);
if
(
pip
){
acquire
(
&
pip
->
lock
);
cv_wakeup
(
&
pip
->
cv
);
release
(
&
pip
->
lock
);
}
}
// XXX necessary because the mtwriteavar() to the same abstract variable
// does not propagate to our scope, since create() has its own inner scope.
mtwriteavar
(
"inode:%x.%x"
,
ip
->
dev
,
ip
->
inum
);
}
else
{
retry:
if
((
ip
=
namei
(
cwd
,
path
))
==
0
)
if
((
ip
=
namei
(
cwd
,
path
))
==
0
){
if
(
omode
&
O_WAIT
){
char
dummy
[
DIRSIZ
];
struct
inode
*
pip
=
nameiparent
(
cwd
,
path
,
dummy
);
if
(
pip
==
0
)
return
-
1
;
cprintf
(
"O_WAIT waiting %s %p %d...
\n
"
,
path
,
pip
,
pip
->
inum
);
// XXX wait for cv_wakeup above
acquire
(
&
pip
->
lock
);
cv_sleep
(
&
pip
->
cv
,
&
pip
->
lock
);
release
(
&
pip
->
lock
);
cprintf
(
"O_WAIT done
\n
"
);
iput
(
pip
);
if
(
myproc
()
->
killed
==
0
)
goto
retry
;
}
return
-
1
;
}
ilock
(
ip
,
0
);
if
(
ip
->
type
==
0
)
{
iunlockput
(
ip
);
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论