Xv6中的系统调用函数

一、xv6中的system call

int fork()  Create a process, return child’s PID. 
int exit(int status)  Terminate the current process; status reported to wait(). No return. 
int wait(int *status)  Wait for a child to exit; exit status in *status; returns child PID. 
int kill(int pid)  Terminate process PID. Returns 0, or -1 for error. 
int getpid()  Return the current process’s PID. 
int sleep(int n)  Pause for n clock ticks. 
int exec(char *file, char *argv[]) Load a file and execute it with arguments; only returns if error. char *sbrk(int n)  Grow process’s memory by n bytes. Returns start of new memory. 
int open(char *file, int flags)  Open a file; flags indicate read/write; returns an fd (file descriptor). 
int write(int fd, char *buf, int n) Write n bytes from buf to file descriptor fd; returns n. 
int read(int fd, char *buf, int n) Read n bytes into buf; returns number read; or 0 if end of file. 
int close(int fd)  Release open file fd. 
int dup(int fd)  Return a new file descriptor referring to the same file as fd. 
int pipe(int p[])  Create a pipe, put read/write file descriptors in p[0] and p[1]. 
int chdir(char *dir)  Change the current directory. 
int mkdir(char *dir)  Create a new directory. 
int mknod(char *file, int, int) Create a device file. 
int fstat(int fd, struct stat *st) Place info about an open file into *st. 
int stat(char *file, struct stat *st) Place info about a named file into *st. 
int link(char *file1, char *file2) Create another name (file2) for the file file1. 
int unlink(char *file)  Remove a file.

二、实例:进程创建与结束

int pid = fork();
 if(pid > 0){
 printf("parent: child=%d\n", pid);
 pid = wait((int *) 0);
 printf("child %d is done\n", pid);
 } else if(pid == 0){
 printf("child: exiting\n");
 exit(0);
 } else {
 printf("fork error\n");
 }

fork()

- 作用:创建新进程(复制自身,产生一个新的子进程)
- 返回值: >0:位于父进程中
          =0 :位于子进程中
          <0:创建子进程失败     

exit()

- 作用:系统调用,用于终结当前进程、释放资源
- 返回值:num
- 状态参数:0-成功,1-失败
- 具体作用:返回当前进程的(退出的或被killed)子进程的PID
           复制子进程的退出状态到等待地址wait()中;

wait(int *status)

- 等待一个子进程退出
- 退出状态在*status
- 返回值:子进程PID

exec(char *file, char *argv[])

- 作用:加载文件到当前进程内存空间,并从入口处开始执行
-      文件为特定格式(ELF),各个部分清晰声明
-      文件通常为程序编译后源码文件
- 返回值:num

三、实例:IO文件读写

 char buf[512];
 int n;
 for(;;)
 {
	 n = read(0, buf, sizeof buf);
	 if(n == 0)
	 break;
	 if(n < 0)
	 {
	 fprintf(2, "read error\n");
	 exit(1);
	 }
	 if(write(1, buf, n) != n)
	 {
	 fprintf(2, "write error\n");
	 exit(1);
	 }
 }

fd描述符

- 输入:0
- 输出:1
- fork()将会复制文件描述符fd到子进程内存空间中
- exec()替换内存空间内容,但保留fd文件描述符
- 两者同样继承offset偏移量

read(int fd, char *buf, int n)

- 作用:从文件描述符fd处读取n个字节,存入buf地址内存空间
- 返回值:读取的字节数
-         0读取完毕

write(int fd, char *buf, int n)

- 作用:从buf地址处提取n字节并写入fd描述符文件
- 返回值:写入字节数
-=n指示读写错误
char *argv[2];
 argv[0] = "cat";
 argv[1] = 0;
 if(fork() == 0) 
 {
 close(0);
 open("input.txt", O_RDONLY);
 exec("cat", argv);
 }

close(int fd)

- 作用:释放文件描述符

四、实例:使用pipes通信

int p[2];
char *argv[2];
 argv[0] = "wc";
 argv[1] = 0;
 pipe(p);         //创建pipes
 if(fork() == 0)  //处于子进程中
 {
 close(0);
 dup(p[0]);   //读取pipes中内容
 close(p[0]); //关闭
 close(p[1]);
 exec("/bin/wc", argv);
 } 
 else  //父进程中
 {
 close(p[0]);
 write(p[1], "hello world\n", 12);
 close(p[1]);
 }

pipes((int p[])

- 作用: 生成管道,存放文件描述符, p[0] 存放读文件描述符and p[1]存放写文件描述符
-       可用于父子进程通信
- 特性:半双工通信,同时通信开两个pipes

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
xv6 添加系统调用需要进行以下步骤: 1. 在 `syscall.h` 文件添加系统调用号。具体来说,你需要在 `SYS_hoge` 列表添加一个新的系统调用号,其 `hoge` 是你的系统调用的名称。例如,如果你的系统调用名称是 `mycall`,则可以在 `syscall.h` 文件添加以下代码: ``` #define SYS_mycall 22 ``` 2. 在 `syscall.c` 文件添加系统调用的具体实现。具体来说,你需要在 `syscalls[]` 数组添加一个新的结构体,其包含你的系统调用的名称和具体的实现函数。例如,如果你的系统调用名称是 `mycall`,则可以在 `syscall.c` 文件添加以下代码: ``` static int sys_mycall(void) { // 在这里编写你的系统调用的具体实现 return 0; } static struct { int nargs; int (*func)(void); } syscalls[] = { { 0, sys_fork }, { 1, sys_exit }, { 0, sys_wait }, { 1, sys_pipe }, { 4, sys_read }, { 4, sys_write }, { 2, sys_close }, { 1, sys_mycall }, // 添加新的系统调用 }; ``` 3. 在 `user.h` 文件添加用户空间的系统调用函数声明。具体来说,你需要添加一个新的函数声明,其包含你的系统调用的名称和参数。例如,如果你的系统调用名称是 `mycall`,则可以在 `user.h` 文件添加以下代码: ``` int mycall(void); ``` 4. 在用户程序调用你的系统调用。具体来说,你可以在用户程序调用你的系统调用函数,例如: ``` #include "user.h" int main(int argc, char *argv[]) { mycall(); // 调用你的系统调用 exit(); } ``` 5. 在内核态的系统调用函数添加系统调用的具体实现。具体来说,你需要在 `syscall()` 函数添加一个新的 `case` 分支,其包含你的系统调用的具体实现。例如,如果你的系统调用名称是 `mycall`,则可以在 `syscall()` 函数添加以下代码: ``` case SYS_mycall: argint(0, &arg1); // 在这里调用你的系统调用的具体实现 return 0; ``` 6. 最后,重新编译 xv6 并运行你的用户程序。在 xv6 的命令行下输入你的程序名称即可运行。例如,如果你的用户程序名称是 `myprog`,则可以通过输入 `myprog` 命令来运行它,其包含了你的系统调用的调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值