Shell设计及系统调用
Shell原理
Shell语法
简单命令:简单命令是(可选的)一系列变量赋值, 紧接着是空白字符分隔的词和重定向符号, 最后以 一个控制操作符结束. 第一个词指明了要执行的命 令, 它被作为第 0 个参数. 其余词被作为这个命令的 参数。 管道命令:管道是一个或多个简单命令的序列,两 个简单命令之间通过管道符号(“|”)来分隔。 列表命令:列表是一个或多个管道组成的序列,两 个管道之间用操作符 ;, &, &&, 或 || 分隔。 其它复杂命令
使用方法
pthread_t mythread; //结构定义 pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER; //定义静态互斥
Linux系统调用
内存管理
malloc(int len)负责为相应变量申请指定的内存空 间大小。
Linux系统调用
使用方法
struct stat sbuf; lstat(argv[1], &sbuf) ;
Linux系统调用
文件管理 int read(int fd,void *buf,int count) read函数从fd说明的文件中读取count个字 节到buf所指向的缓冲区。函数的返回值是 实际读写的字节数。 int write(int fd,void *buf,int count) write函数把count个字节从buf写入到fd说 明的文件中。函数的返回值是实际写入的 字节数。
使用方法
pid_t pid; pid = fork();
//定义进程号 //进程创建
Linux系统调用
进程管理
wait系列函数 pid_t wait (int *status); pid_t wait3(int *status,int options,struct rusage *rusage) ; pid_t waitpid(pid_t pid, int *status, int options) ; waitpid函数的功能是使得父进程的执行得以保持,直到子进 程退出(即使父进程先处理完,也要等到子进程结束)。子 进程退出时,父进程收集子进程的信息,并继续执行直到退 出。 使用方法 pid_t pid; //定义进程号 pid = fork(); //进程创建 waitpid(pid, NULL, 0); //等待子进程退出
Shell设计
编译工具
gcc
gcc 是 GNU 的 C 和 C++ 编译器 例子: gcc –o hello –Wall hello.c
Shell设计
常用命令
mkdir usb mount /dev/sdd1 /mnt/usb umount /mnt/usb
Linux系统调用
execl, execlp, execle, execv 等 使用方法 execl(“/bin/ls”, “/bin/ls”, “-l”,“/etc”,NULL); //调用 ls 命令
Linux系统调用
文件管理 stat函数和lstat函数为用户访问文件的I结点 信息提供了基本的接口。这两个函数用这些 信息来填充一个类型为struct stat 的结构。
Shell设计及系统调用
Shell原理 Shell设计及实验要求 Linux系统调用
Shell原理
Shell
命令解释器 操作系统和外部的接口,即操作系统最外 面的一层。 提供了用户和操作系统之间的通讯方式。
演示
man bash
Shell原理
shell命令分类
内建命令 例子:cd 外部命令 例子:cp、rm
谢 谢!
Shell原理
Shell命令的执行
当外部程序(命令)运行的时
bash创建一个自身的拷贝,子进程和父进程拥有一样的 环境,唯一个区别只有进程号。这个过程被称作内核空间 创建进程 forking 。 创建子进程后,子进程的地址空间被新进程数据覆盖,子 进程装配相应的执行程序。此步骤通过 exec 系统调用完 成。 fork-and-exec 机制把旧的命令转化成新的,新程序的执 行环境还是和原来相同,包括输入输出设备的配置,环境 变量和优先级。 shell 直接执行那个命令,而不创建新的进程。
使用int pipe(int fd[2])创建管道的标准编程模式如下:
int pipe(int fd[2])
1) 创建管道; 2) 使用fork( )方法创建两个(或多个)相关联的进程; 3) 使用read()和write()方法操作管道; 4) 管道使用完毕后用close(int fd)方法关闭管道。
Linux系统调用
系统调用流程
4、从系统调用中返回后,最终执行 syscall_exit,并调用 resume_userspace 返回 用户空间。然后继续在 C 库中执行,它将返回 到用户应用程序中。
Linux系统调用
系统调用表和各种链接
Linux系统调用
主要系统调用
进程管理 文件管理 进程通信 线程 动态内存分配
系统调用
内核提供的功能强大的函数 用户空间程序和内核提供的服务间的接口 跨越用户空间与内核之间的界限
Linux系统调用
系统调用流程
1、每个系统调用通过一个单一的入口点多路传 入内核。eax 寄存器用来标识应当调用的某个 系统调用,这在 C 库中做了指定。
Linux系统调用
系统调用流程
系统调用表: usr/src/linux/arch/i386/kernel/entry.S 头文件:usr/include/unistd.h
Linux系统调用
进程管理
pid_t fork( ) fork函数的功能是创建一个新进程,运行与当前进 程相同的程序,成功将返回进程号,根据进程号, 可处理不同的事情。
Linux系统调用
进程通信
pipe使用方法
int pipefds[2]; //定义管道文件描述符 pipe(pipefds); //管道创建 close(pipefds[FD_WRITE]); //关闭管道写 close(pipefds[FD_READ]); //关闭管道读
Linux系统调用
Linux系统调用
进程通信 signal(SIGUSR1,func)
当收到SIGUSR1信号时,就执行func(),如果 SIGUSR1信号未到,则系统登记func函数,待其 信号到时再调用执行。
将创建一个管道和两个文件描述符:fd[0], fd[1]。 其中fd[0] 文件描述符将用于读操作,而fd[1] 文件 描述符将用于写操作。pipe()的成功返回值是0。
当内建命令被用作一个简单命令时
Shell设计
程序框架
1、打印提示符并等待用户输入 2、获取用户输入 3、分析用户输入 4、解释并执行命令 5、当用户输入 logout/exit 退出shell
Shell设计
实验要求
实现基本的shell命令解释器,能够执行简 单命令,如cp、rm等外部命令,同时也 可实现自己定义的内部命令 实现管道命令,支持重定向 其它增强功能 实验检查时间:考试之前
线程( PThread)
pthread_create
创建一个真实活动的线程。
将两个线程合并为一个线程。 在线程程序中这些调用执行了不可或缺的功能。他们提供了一 种相互排斥的方法(互斥对象即由此得名)。两个线程不能同 时对同一个互斥对象加锁。
pthread_join
pthread_mutex_lock/pthread_mutex_unlock
底层系统调用的使用
方法一:通过 syscall 函数调用由其索引所标识的 新函数 例子:
#define _NR_getjiffies 320 syscall( _NR_getjiffies );
Linux系统调用
底层系统调用的使用
方法二:创建函数调用,这些函数调用必须匹配内 核中的系统调用索引(这样就可以调用正确的内核 服务),而且参数也必须匹配。Linux 提供了一组 宏_syscall来提供这种功能。
如何跟踪系统调用
strace: Linux 内核提供的一种非常有用的方法来跟踪某个 进程所调用的系统调用以及该进程所接收到的信号。 它可以在命令行中执行,使用希望跟踪的应用程序 作为参数。 例: 如果您希望了解在执行 date 命令时都执行了哪些 系统调用,可以键入下面的命令: strace date
2、当加载了系统的 C 库调用索引和参数时, 就会调用一个软件中断(0x80 中断),它将 执行 system_call 函数(通过中断处理程 序)。
Linux系统调用
系统调用流程
3、system_call 这个函数会按照 eax 内容中 的标识处理所有的系统调用。在经过几个简 单测试之后,使用 system_call_table 和 eax 中包含的索引来执行真正的系统调用了。
Linux系统调用进程管理exec系列
完成对其它程序的调用。用户在调用 exec 函 数时,进程的当前映像将被替换成新的程序, 如果你成功调用了一个 exec 函数,函数的调 用将不会返回,而在你原来进程所占用的内 存空间里运行你所调用的程序。通常用子进 程调用运行 exec 函数,父进程等待直到子进 程结束。