UNIX系统程序设计教程

2019-02-15 23:59

第一章:生成一个Process(进程)

进程是什么?简单地说,进程就是在执行状态下的一个程序(包括CPU状态,所占内存的状态,等等)

A进程生成了B进程,也就是说,A程序在执行的时候,又生成了另一个进程B。这个时候,我们可以把A进程叫做父进程,把B进程叫做子进程。 例程序:

// Usage : ./a.out 20 #include

int main( int argc , char *argv[]) {

int dep_time;

dep_time = atoi( argv[1] )*60 ; //将参数中给出的20(分钟)转换成整型的秒数 if( fork()==0 ) //生成子进程,然后父进程中止 {

sleep( dep_time );

fprintf( stderr , !!!!!!!!\\n); }

return 0; }

上面的程序是一个闹钟程序。当你执行之后。程序不会显示什么,而是一下就回到UNIX的提示符下。但是你在命令行中指定了20分钟后你有事,那么在你执行这个程序之后20分钟,他会提醒你到时间了。

本程序只是做示例用,没有检查参数是否正确,等等。

生成一个新的进程,可以使用 fork() 函数 。以下说说fork()函数。

头文件: #include 形式 pid_t fork(); 参数 无

返回值 成功时: 父进程中:子进程的PID (Process ID) 子进程中:0

失败时: 父进程中:-1

由于失败,没有生成子进程;

fork()刚执行完的时候,子进程和父进程是完全一模一样的两份进程(当然,PID是不一样的)。他们的各个变量的值都是一样的,而且都认为自己已经执行完fork()了。fork()后,区分父进程和子进程,只要看fork()的返回值就行了。 if( fork()==0 ) printf(这是子进程); else printf(这是父进程);

同理:

if( fork()==0 ) {

//接下来要子进程做的工作 } else {

//接下来要父进程做的工作 }

一般,我们会把fork()返回给父进程的值保存下来(其实就是子进程的PID),等到需要结束子进程的时候,我们关掉他,如下:

pid_t child_pid ; child_pid=fork(); if( child_pid==0 ) {

// ... ... } else {

// ... ... }

// ... ...需要结束子进程的时候

kill( child_pid , SIGKILL ) // kill()函数是用来发给另一个进程一个消息的。以后再讲。

先写这些,试试手。喜欢就顶。要是没人爱看我就不写了。呵呵。省得大家说我乱贴垃圾。

以后计划贴的东西:

在程序中执行UNIX命令或者另一个程序 取得环境变量并利用

UNIX文件系统(在程序中取得分区信息,等等) 使用管道操作达到在各进程互相交流数据 信号(signal)

进程间共享内存

用message实现进程间共享信息

第二章:在程序中执行UNIX命令或者其它程序

在UNIX下,像DOS的command.com那样的程序,我们称之为外壳(shell)。外壳就是一个命令解释器,你在外壳的提示符下输入命令(如同DOS的提示符一样),系统便会执行。

DOS的提示符一般是C:\\>,当然,你想改成什么样就能改成什么样,又当然,像BBS一样贴张图上去是不太现实的。

UNIX的提示符根据外壳的不同是不同的。

为了更好地说明本章想讲解的内容,我们先做一个外壳试试(玩具级别的)。我们给他起名叫SSH(Sohu Shell)吧。想取名叫CSH,可惜CSH在没生我之前就有了。呵呵。

/* 简单的外壳程序 */ #include int main() {

static char prompt[64]=> ; char command[256]; int st;

fprintf(stderr,%s,prompt); // 在屏幕上输出提示符 while(gets(command)!=NULL) // 取得命令 {

if(fork()==0) // 生成子进程

{ // 这里是子进程接下来要做的事

if( execl(command,command,(char *)0)==(-1) ) // 上一句是执行命令

exit(1); // 当出错时子进程异常中止 } else

{ // 父进程

wait(&st); // 等待子进程结束 fprintf(stderr,%s,prompt); // 输出提示符,等待命令 } }

return 0; }

执行方法: %./ssh >/bin/ls

当前目录下文件名一览 >Ctrl+D %

普通的外壳在执行exit命令后会关闭。也就是说,退出一层外壳。咱们这个程序现在还做不到。愿意的话加上这个功能试试好了。所以要关闭这个外壳就得来点狠的。Ctrl+D,Ctrl+C什么的。再不你就再开一个外壳然后ps -ef再kill。再狠一些……拆硬盘,拨电源

我们这里有了一个新的函数:execl()。其实他是一组函数中的一个。这组函数如下: 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

用过TC的朋友应该知道,TC的Process.h里有一个system()函数。这组函数其实和system()的功能差不多。

比方说:

execl( /bin/ls , /bin/ls , -al , /home , (char *)0 ); 或者

char *argv[];

strcpy( argv[0] , /bin/ls ); strcpy( argv[1] , -al ); strcop( argv[2] , /home ); execv( /bin/ls , argv );

都相当于在命令行下敲入了/bin/ls -al /home并且回车。(引号不是命令里的。是我解释时加上去的。别看混了)。

execle()和execve(),函数名最后一个字母都是e。就是说,这两个函数在调用其它程序的同时,还可以把环境变量一起传给被调程序

execlp()和execvp(),函数名最后一个字母都是p,就是说,这两个函数在使用的时候,就算你不指定命令文件所在的路径,它也会根据环境变量PATH去挨个地方找。找着就执行。找不着拉倒。 比方说:

setenv $path = ( /bin $path ) 这句话将环境变量PATH的第一个路径设为/bin。这是在SHELL下执行的。C里没这东西吧。 在程序中这样用这个函数

execlp( ls , ls , -al , /home , (char *)0 );

与上面的效果一样。当然。如果你PATH变量没设好的话。它就不一定找到哪儿去了。

还有一个函数是wait(),说明如下: #include

pid_t wait(int *stat_loc);

返回值就是一个PID了。忘了PID是什么意思的朋友光顾一下我上一篇贴子。

它的参数有些意思。其实它与你的子进程用什么方式结束有关系。当你的子进程以exit()方式结束的话,stat_loc所指向的地址的前8位将会是exit()的参数的后8位,而stat_loc所指向的地址的后8位是0。比方说:你的子进程是exit(1);那stat_loc所指向的地址的内容应该是0000 0001 0000 0000。

exit(): #include

void exit(int status);

就算你在程序中没写exit()函数,编译器也是认为你是在最后加入了这个函数。

第三章:增强ssh的功能(使用环境变量)

还记得上次做的那个ssh吧?这回咱们把它再改一改。 大家知道。C语言的main函数是这样的: int main( int argc , char *argv[] , char *envp );

前两个不用说了吧。其实知道前两个的话应该也知道第三个:取得系统环境变量。 UNIX和DOS一样。有着各种各样的环境变量(明确地说,应该是比DOS用得更广泛)。比方说常用的$PATH,$HOME,$USER等等。如果用的是csh,可以改 ~/.cshrc或者干脆直接在命令行下设就行了。这些是UNIX的东西,不属于我们在C/C++讨论的东西了。有兴趣的朋友可以到UNIX版去看一看。

下面是一个取得系统环境变量并输出的小程序

/* getenv.c 取得系统环境变量并输出 */ #include

int main ( int argc , char *argv[] , char *envp[] ) { int i;

for( i=0 ; envp[i]!=NULL ; i++ ) {

printf( %s\\n , envp[i] ); }

return 0; }

编译执行后应该是这样: %./getenv DISPLAY=:0.0

HOME=/home/syuui USER=syuui

以及你的系统中其它的环境变量。

想一想它是怎么运行的:当你在命令行下敲入getenv并回车,shell就fork出一个新的进程,然后让这个进程去执行getenv,并把现在系统中的各个环境变量存入到envp里


UNIX系统程序设计教程.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:小学四年级乘法除法应用题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: