操作系统设计与实现 第一章 引言(二)

1.4 系统调用

请记住以下事实:

    任何单CPU计算机一次只能执行一条指令。

如果一个进程正在用户态下运行一个程序,然后它需要一个系统服务,如读取文件数据,那么它就必须执行一个陷阱或系统调用指令,把控制权交给操作系统。操作系统通过检查此次调用的参数,判断出该进程所需要的服务类型,然后去执行相应的服务功能并把控制权交还给用户进程,从系统调用后面的那条指令开始执行。

从某种意义上来说,发出一个系统调用类似于发出一个特殊的函数调用,两者的区别仅在于,发出系统调用后,将进入内核或其他的特权操作系统组件,而函数调用则不会这样。

MINIX3总共有53条系统调用,被分为6大类:

进程管理、信号、文件管理、目录及文件系统管理、保护、时间管理。

1.4.1 进程管理的系统调用

这里写图片描述
在MINIX3中,fork是创建一个新进程的唯一途径。它实际上创建的是原进程的一个副本,包括文件描述符、寄存器的值等,所有内容都是完全相同的。

调用fork后,原进程与新进程各自执行互不相关。一个进程的变量值发生变化,并不会影响到另一个进程(代码段不可修改,父子进程共享)。

正常情况下,如果fork函数的返回值为0,表示当前进程是子进程;如果返回值为一个正整数,则表明当前进程是父进程,而该整数即为子进程的标识号PID。因此,在调用fork后,父子进程内容完全相同,但是通过函数返回值可以将父子进程区分开来。

多数情况下,在执行完fork之后,子进程需要执行一段与父进程不同的代码。为了等待子进程结束,父进程会执行一个waitpid系统调用,该调用将使父进程阻塞,直到子进程结束。

#define TRUE 1

while(TRUE)//无限循环
{
    tpye_prompt();//在屏幕上显示提示符
    read_command(command, parameters);//从终端读取输入

    if(fork()!=0)//创建子进程
    {
        /*Parent code.*/
        waitpid(-1, &status, 0);//等待子进程退出
    }
    else
    {
        /*Child code.*/
        execve(command, parameters, 0);//执行命令
    }
}

一般情况下,execve函数有三个参数:待执行的文件名、指向参数数组的指针和指向环境数组的指针。

在MINIX3中,进程的内存空间被分为三个部分:代码段(即程序代码)、数据段(即变量)、栈段。数据段从下往上增长,而栈从上往下增长。在这两者之间的是空闲的地址空间。栈的增长是随着程序的执行自动进行的,而数据段的扩展则需要通过brk系统调用来显示完成。

这里写图片描述

下一个系统调用是getpid,返回调用进程的进程标志号PID。在调用fork时,只有父进程能够获得子进程的PID。如果子进程想要知道它自己的PID,就必须使用getpid。

最后一个系统调用是ptrace,它只要用来对被调试的程序进行控制。通过ptrace,调试器可以读、写被控进程的地址空间,并进行其他方式的管理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值