20135203齐岳 信息安全系统设计基础第十二周实践总结

20135203齐岳 信息安全系统设计基础第十二周实践总结

进程和程序:编写命令解释器sh

一个程序如何运行另一个程序

程序调用execvp:比如,为了运行ls -la,一个程序调用execvp("ls"+arglist)。arglist是命令行的字符串数组,数组的第一个元素为程序名称,最后一个元素必须是null。

exec1.c编译并运行程序结果如下:

744942-20151129114058766-918630353.jpg

可以看到源代码中第二个printf语句消失了,原因是调用execvp函数时,内核将新程序载入到当前进程,替代当前进程的代码和数据。

exec2与exec1的区别就在于,execvp函数调用的语句变成了

execvp( arglist[0] , arglist );

编译运行结果与exec1.c完全相同,说明arglist数组的第一项为要运行的程序的名称。

exec3.c中给出了一系列的exec函数调用方法,其不同用法如下图所示:

744942-20151129114113594-2146990170.jpg

argv数组-exec函数参数列表

将makeargv.c和freemakeargv.c制作成静态库,运行argtest.c结果如下:

744942-20151129114135375-964486413.jpg

envp数组-exec函数环境变量列表

envp变量指向一个以null结尾的指针数组,每个指针指向一个环境变量串,其中每个串都是形如“NAME=VALUE”的名字—值的对应。

evrion.c作用是打印environ数组中的每一项内容(表示什么的路径?)

744942-20151129114154891-195216840.jpg

evrionvar.c调用了getenv函数,在环境数组中搜索字符串“name=value”。如果找到了就返回一个指向value的指针。

744942-20151129114212438-1678282181.jpg

带提示符的shell

psh1.c是Unix shell的第一个方案,要求每个字符串单独输入,第一个是程序名,然后依次是程序参数。

代码包括两步,(1)一个字符串,一个字符串构造参数列表argist,最后在数组末尾加上NULL;(2)将arglist[0]和arglist数组传给execvp。

程序正常运行,execvp命令指定的程序代码覆盖了shell程序代码,并在命令结束之后退出,shell就不能再接受新的命令。

744942-20151129114232672-823123490.jpg

为了解决这个问题,程序通过调用fork来复制自己。

调用fork函数之后内核的工作过程:

  • 分配新的内存块和内核数据结构
  • 复制原来的进程到新的进程
  • 向运行进程集添加新的进程
  • 将控制返回给两个进程
建立一个新的进程

父进程通过调用fork函数创建一个新的运行子进程。

调用一次,返回两次。一次返回到父进程,一次返回到新创建的子进程。

744942-20151129114248328-197616162.jpg

子进程创建新进程

子进程不是从main函数开始,而是从fork返回的地方开始被创建

744942-20151129114300110-1689124137.jpg

分辨父进程和子进程

运行pid_t fork(void)语句,不同的进程fork的返回值是不同的,子进程返回0,父进程返回子进程的pid,出错则返回-1。

744942-20151129114318110-1285757980.jpg

744942-20151129114329016-335337866.jpg

父进程如何等待子进程的退出

进程通过调用wait函数等待子进程的退出。wait首先暂停调用它的进程直到子进程结束,然后wait取得子进程结束时传给exit的值。

waitdemo1.c显示了子进程调用exit触发wait返回父进程的过程。

744942-20151129114346844-1802766075.jpg

体现了wait的两个重要特征:

  • wait阻塞调用它的程序直到子进程结束
  • wait返回结束进程的PID

waitdemo2.c显示了wait函数告诉父进程子进程是如和结束的,通过传递给wait的参数。父进程调用wait时传一个整型变量地址给函数,内核将子进程的退出状态保存在这个变量之中。

744942-20151129114405953-1082641827.jpg

实现一个基本的shell:psh2

744942-20151129114423157-1097209259.jpg

I/O重定向和管道编程

shell重定向I/O

通过使用输出重定向标识,命令cmd>filename告诉shell将文件描述符1定位到文件,则shell就将文件描述符与指定的文件连接起来。

程序则不断地将数据写入到文件描述符1中,而不会意识到数据的目的地已经改变了。

listargs.c表明了程序会忽略命令行中的重定向符号。

如何将stdin定向到文件

方法一:close then open

调用close(0)将标准输入与终端设备的连接挂断,然后使用open(filename,O_RDONLY)打开一个想连接到stdin上的文件。

方法二:open..close..dup..close

调用dup(fd)将文件描述符fd做一个复制,此次复制使用最低可用文件描述符号,因此获得文件描述符0将磁盘文件与文件描述符0连接在一起。

744942-20151129114454407-2040443984.jpg

whotofile&结果

744942-20151129114507532-852296033.jpg

744942-20151129114521203-2002197840.jpg

创建管道

调用pipe来创建管道并将其两端连接到两个文件描述符,array[0]为读数据端的文件描述符,而array[1]则为写数据端的文件描述符,内部则隐藏在内核中,进程只能看到两个文件描述符。

pipedemo.c展示了如何创建管道并使用管道来向自己发送数据。

744942-20151129114542250-2077774744.jpg

pipedimo2.c说明了如何将pipe和fork结合起来,创建一对通过管道来通信的进程。

744942-20151129114558719-80289185.jpg

信号处理的例子

捕捉信号

按下Ctrl-C之后

744942-20151129114619203-424418586.jpg

忽略信号

744942-20151129114639407-1195975957.jpg

为处理信号做准备

744942-20151129114651703-295021403.jpg

遇到的问题

1.evrion数组返回的路径是什么的路径?

2.stdinredir1编译有警告,运行无结果

744942-20151129114707844-1897599838.jpg

参考资料

《[Unix-Linux编程实践教程].Understanding.UNIX_LINUX.Programming》
《深入理解计算机系统》

转载于:https://www.cnblogs.com/July0207/p/5004533.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值