注:本文来自“网易”博主,仅阅读,学习

第一章:什么是系统编程 
UNIX系统编程,简单的说就是“C语言+系统调用(system call)”,学会了C语言再知道一些系统调用的方法,其实就可以进行UNIX系统编程了。那什么又是系统调用呢,其实初学者就把它看当成是函数用就可以了。这些“函数”是干什么用的呢,大家知道操作系统内核管理着我们的计算机资源,比如CPU,内存,硬盘等等。应用程序是无法直接访问到它们的。那我们想利用这些资源怎么办呢,内核就给我们提供了一个接口,我们可以利用这个接口来进行计算机资源的使用。内核也通过接口来判断我们的使用请求是否合法,合法的的提供资源,不合法的给与干掉。就好比是金库,银行和储户。金库里有要多地人民币,这就是资源。然而我们储户却无法直接接触到这些可爱的人民币,因为它们是通过银行来管理的,银行就好比是内核。但我们怎么样才能从金库里取出钱来呢,我们可以去银行窗口办理存款取款手续,这就是系统调用。当然,每个人的取款限额都不一样,大款的存款多,他可以取几百万甚至更多,而我存款少,取出一万块就已经不错了。这就是用户的系统调用权限不同。还有就是银行行长,他对这个金库的权限更大(root),当然他的责任也更大,他的一个错误决定有可能导致银行破产。这事可就大了。还有一种情况,一个在银行里没有什么存款的人,却通过一些技术手段,得到了一个大款的密码甚至是伪装成银行行长,把金库里的钱全提走了,这就是黑客。想想这种感觉你就知道为什么世界上有这么多黑客乐此不疲了。还有一些人没有什么“技术含量”直接“抢银行”,把你的计算机都抱走了。那你只有哭了,金库里的钱丢了,好在“房子”还在呀,这回连“房子”也丢了。依照这个比喻,那木马是什么呢?对,就是你的银行职员里出了内奸了。哈哈。好了不胡扯了,我了这么多例子就是想告诉大家,银行(内核)本身来说还是十分坚固稳定的,问题出在如何通过窗口(系统调用)安全地使用它。这也是学习UNIX系统编程是应该注意的问题。从下一个帖子开始说说说进程(process)和如何生成一个进程。
第二章 进程的生成(1) 
    先说说什么是进程?假设你编好了一个程序,在它没有被调用之前,它只是乖乖地躺在你的硬盘上,什么事情都不干。好不容易编出来的不干活,这是我们不能容忍的。所以我们要把它调到内存里,然后通过CPU去执行它。所以说,进程就是一个在执行状态下的程序。 
我们可以通过

$ps –e

命令来查看一下,计算机里所运行的进程有哪些。 
那我们计算机里这么多的进程的又是从哪里来的呢,我们可以通过

$ps –axwf

来看到关于进程的一张家谱。其实,系统中的所有进程都是通过另一个进程生成的(除了0号进程以外),如果,A进程生成了B进程,那么可以把A进程叫做父进程,把B进程叫做A进程的子进程。也就是说,UNIX系统所有的进程都与其它进程保持着父子关系。

下面我们来看一个简单的例子

#include<stdio.h>#include<sys/types.h>#include<unistd.h>int main( int argc , char *argv[]){int time;time = atoi( argv[1] )*60 ;       //将参数中的分钟换成秒数if( fork()==0 )       //生成子进程,括号里是子进程的代码{sleep( time );fprintf( stderr , "it is time to alarm!\n");}return 0;}

执行时输入

$./a.out 2

这是一个简单的闹钟程序。你把它执行后,看似系统没有什么反映,其实不是,在后台你已经生成了一个进程,来监视时间。如果你用ps命令查看就能看到它。这时你可以接着干你自己的事情。等到了你设定的时间之后这个进程会提示你时间已经到了。这个程序虽不完善(没有进行输入参数的检查),但可以简单的告诉大家如何生成一个进程。 
    为了生成一个新的进程,这里使用了 fork() 这个系统调用。它的作用是将父进程的各个变量的值复制给子进程,也就是说当你调用了fork()的那一刻,系统就为你生成了一个和父进程完全一样的进程。当然我们不想要一个父亲一样的孩子,孩子要有自己的个性,那我们如何来赋予孩子自己的个性呢?让我们先来看看fork()这个系统调用的概要。

头文件       #include <sys/types.h>#include <unistd.h>形式       pid_t fork(void);返回值          成功时:        父进程中:子进程的进程号(>0)子进程中:=0失败时:        -1

根据上面fork()的特性,我们可以通过fork()的返回值区分父进程要做的事和子进程要做的事。例如,

pid_t pid ;pid=fork();if( !pid){//子进程要做的事}else if(pid >0){//子进程生成失败时,父进程要做的事}else  //pid<0{//子进程生成失败时,父进程要做的事}

好,我们现在已经学会了生成一个子进程了。但它还是遗传了许多父进程的特性,有可能大家会想,能不能用我们生成的子进程来执行另一个与父进程没有任何关系的程序呢。当然是可以的,比如我们常说的shell就是就是这个样子。shell本身也是一个进程当你输入命令回车以后,shell会生成一个子进程来执行你的命令,这条命令可以和shell没有丝毫关系。为了更好的说明问题我们先来做一个简单的shell。当然是最简单的那种。

#include<stdio.h>#include<sys/types.h>#include<unistd.h>int main(){static      char prompt[64]="> ";char    command[256];int   st;fprintf(stderr,"%s",prompt);    //  屏幕上的输出提示符while(gets(command)!=NULL)  //  取得键盘输入{if(fork()==0)     //  生成子进程{         //  子进程要做的事execl(command,command,(char *)0)==-1 //执行所输入的命令}else{         //  父进程要做的事wait(&st);  //  等待子进程结束fprintf(stderr,"%s",prompt);  //  输出提示符,等待命令}}return 0;}

好了我们保存,编译,执行以下看看

$./a.out>/bin/ls  //这里必须输入命令的完全路径当前目录下文件名>Ctrl+D 退出程序$

这样我们的一个最初级shell就做好了。虽然它还很弱,还有着安全上的漏洞(使用了gets()),甚至连自己退出都不能,但起码可以让我们看到一个shell是如何执行的了。其实,一个复杂的shell最基本的东西也就使这些。大家要是有兴趣的话可以将gets()换掉,再加上退出功能。

我们再说说程序中出现的一个新的函数execl()。其实它是exec函数组中的一个。这组函数有:

int   execl( path , arg0 , arg1 , ... , argn , (char *)0 );int   execv( path , argv );int   execle( path , arg0 , arg1 , ... , argn , (char *)0 , envp );int   execve( path , argv , envp );int   execlp( file , arg0 , arg1 , ... , argn , (char *)0 );int   execvp( file , argv );
参数定义如下:char *path;char *file;char *arg0 , *arg1 , ... , *argn;char *argv[];char *envp[];返回值:        成功时:所执行的命令将会覆盖现有的进程,所以无返回值失败时:-1

比如说我们在shell里执行

$ /bin/ls –l

这个命令,实际上shell调用的是

execl( "/bin/ls" , "/bin/ls" , "-l"  , (char *)0 );

的一个系统调用 
这个函数组函数有6个,用法就不一一说明了,大家可以参看一下其它资料。这里只告诉大家它们的用处,exec函数组就是用来调用一个可执行程序。还有一点很重要,一但进程调用了exec函数那么写在exec函数后面的进程代码将会被覆盖,变成无效的代码了。 
例如下面一段代码,我们想在execl执行后输出一段文字列,这是办不到的。

 if(fork()==0)     //  生成子进程{         //  子进程要做的事execl(command,command,(char *)0)==-1 //执行所输入的命令fprinf(stderr,"lalalalalalalalala!");  //}else{         //  父进程要做的事wait(&st);  //  等待子进程结束fprintf(stderr,"%s",prompt);  //  输出提示符,等待命令}

还有一个函数wait(),它的概要是

#include <sys/types.h>pid_t wait(int *status);

返回值就是子进程的进程号 
它的参数是个指针。C语言里讲过,一个函数想有一个以上的返回值时,你可以将想返回的变量的地址作为函数的参数。比如说将数组地址作为函数的参数等等。其实这里的status就是这个道理,它的值与子进程的结束方式有关系。当你的子进程以exit()方式结束的话,status所指向的地址的前8位将会是exit()的参数的后8位,而status所指向的地址的后8位是0。例如子进程是exit(1);那status所指向的地址的内容应该是0000 0001 0000 0000。还有如果子进程是通过信号(signal)终止的(信号我们以后再讲),那么我们也可以通过status的值来判断是哪一个信号终止了这个子进程。(详见man) 
我们为什么还要在父进程中调用wait(),这涉及到进程状态的概念,我们稍候再说。

UNIX系统编程(1)相关推荐

  1. 5w字总结 Unix系统编程学习笔记(面试向)(Unix环境高级编程/Unix环境程序设计)

    文章目录 一.计算 C语言的数据表示与处理 计算 C语言的基本运算操作 内存表和符号表 类型转换 函数类型的分析 指令 复合指令 句法 函数 函数激活(Activation Record) 函数激活定 ...

  2. UNIX系统编程(一)

    看了<Linux程序设计>100来页,不得不吐槽一下翻译,实在没办法,在豆瓣上找到这本书<Unix/Linux编程实践教程>,翻了那么几十页,就爱上了这本书了. 下面是一些概念 ...

  3. UNIX系统编程(2)

    注:本文来自"网易"博主 第三章:文件系统 这回我们来说一下UNIX的文件系统.由于一般情况下UNIX机的硬盘会很大,所以一般你可以给它分成几个区,而每个分区又都可以有独立的文件系 ...

  4. Linux/Unix系统编程手册 第三章:系统编程概念

    本章介绍系统编程的基础概念和一些后续章节用到的函数及头文件,并说明了可移植性问题. 系统调用是受控的内核入口,通过系统调用,进程可以请求内核以自己的名义去执行某些动作,比如创建子进程,执行I/O操作, ...

  5. UNIX系统编程小结(三)----进程相关

    进程即一个程序的动态执行.引用apue上的一句话:"A thorough understanding of the UNIX System's process control is esse ...

  6. linux/unix系统编程手册11-15

    title: linux/unix编程手册-11_15 date: 2018-05-27 11:53:07 categories: programming tags: tips linux/unix编 ...

  7. Linux/UNIX系统编程手册gg

    Linux系统: "所见皆文件" 一个比较好的博客 一.Linux基础操作 Linux系统目录: bin:存放二进制可执行文件 boot:存放开机启动程序 dev:存放设备文件: ...

  8. unix系统编程小结(二)------文件和目录

    一.对linux的安全机制的一点感悟 各种权限,read,write,execute,set-user-ID,set-group-ID,sticky bit,对目录的权限,对文件的权限,用于保证系统安 ...

  9. Unix系统编程()发送信号kill

    与shell的kill命令类似,一个进程能够使用kill系统调用向另一进程发送信号. 之所以选择kill作为术语,因为早期UNIX实现中大多数信号的默认行为是终止进程. #include <si ...

最新文章

  1. python标准化输出_Python设定模板及标准化输出,输入
  2. Docker 在容器中部署静态网站
  3. 回顾线程的竞争机制-重量级锁
  4. 年龄与疾病(信息学奥赛一本通-T1106)
  5. 如何在GitHub上发现优秀的开源项目
  6. 某集团BI决策系统建设方案分享
  7. react classname多个_React全家桶简介
  8. AI也能精彩表达:几种经典文本生成模型一览
  9. 解决库仑计初始化卡死问题
  10. 如何将.sql文件导入数据库
  11. 怎么用linux给苹果手机降级,如何查询iOS可降级版本?苹果iOS随意降级工具或即将到来...
  12. win7 mysql怎么配置环境变量_MySQL Win7 64位 下载、安装与配置图文教程
  13. lol全队消息怎么发_英雄联盟如何发全部消息,LOL怎样发送消息给全部
  14. html的网页主题标记是什么,html标记是什么
  15. Riot Game前高管:游戏玩家将成为Web3真正粉丝的15大原因
  16. 称重管理系统服务器不通,称重管理系统使用方法(二)
  17. [C] 不撞南墙不回头——深度优先搜索
  18. 旋转编码器旋钮程序_让我们使用SwiftUI构建具有旋转手势的复古音频旋钮
  19. 西恩科技更新招股书:IPO前大手笔分红“套现”, 赵志安为实控人
  20. 罗切斯特大学计算机博士,罗切斯特大学生物博士排名,千万得慎重点看清

热门文章

  1. 正则表达式快速入门(归纳版)
  2. 明年就翻身系列:AMD 2017统治PC、服务器市场?
  3. 《需求设计:构建用户想要和需要的产品》—— 导读
  4. SendTextMessage 等方便的消息发送函数
  5. CDataBaseEngineSink::OnRequestPlatformParameter 数据库异常:查询超时已过期 [ 0x80040e31 ]...
  6. 《一条狗的回家路》曝中国风海报 霍思燕为狗狗配音
  7. JDBC操作之连接和关闭mysql数据库
  8. 接口测试--version2
  9. ubuntu 命令收集
  10. 全部编程皆为Web编程