77范文网 - 专业文章范例文档资料分享平台

UNIX系统程序设计教程(4)

来源:网络收集 时间:2019-02-15 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

read( fd[0] , &j , sizeof(j) ); //从管道读数据 switch(result[i][j]) {

case 0:

printf( You won\\n ); break; case 1:

printf( Same\\n ); break; case 2:

printf( You lost\\n ); }

close(fd[0]); close(fd[1]); return 0; }

/* child.c */ #include

int main(int argc , char *argv[]) { int i,j, read_fd, write_fd;

read_fd=atoi( argv[1] ); //设定输入用管道 write_fd=atoi( argv[2] ); //设定输出用管道

read( read_fd , &i , sizeof(i) ); //从管道中取得数据 srand( i+getpid() ); //设定随机数的种子数 j=rand()%3; //生成随机数

write( write_fd , &j , sizeof(j) ); //写向管道 close( read_fd ); close( write_fd ); return 0; }

编译执行父程序即可。

这种管道是用来在父子进程间传递数据的。如同大家在程序中所见:父进程开辟管道,然后生成子进程执行子程序,并将管道参数作为main()函数的参数传给子程序。通过一个相同的管道实现读写。开辟管道时,我们用到了这个函数:

int pipe( int fd[2] ); 开辟一个管道

参数fd[2]是一个有两个元素的数组。可以看成是两个管道的记述子。fd[0]用来读,fd[1]用来写。

返回值: 成功时:0 失败时:-1

读取/写入管道时,我们用到了下面函数

读取管道中的数据

int read( int fd , char *buf , unsigned int nbyte ); 向管道中写入数据

int write( int fd , char *buf , unsigned int nbyte );

其中,fd是管道记述子,也就是我们前面说的fd[0]或者fd[1],buf装数据,nbyte指定读/写数据的数量,单位是字节。成功时返回0,失败时返回-1。

由于准备考研。这篇文章耽误了一些时日。最近还有些事,也许下一篇也得几天后才能再贴。

另外,在此向诸位致歉。我的程序是在学校的UNIX下写的,一般是用软盘带回来,写上一篇贴子程序的时候没有带软盘,只好打印出来回来再敲。在输入的时候有一个错误(现已改正)

int main( int argc , char *argvp]); 应为

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

第七章:UNIX进程(Process)及信号(signal)

在进程执行过程中,如果出现什么事件(event),系统将会给进程一个信号。进程可以在得到这个信号后做些适当的处理。

还是与以前一样,咱们先来个小程序吧。

/* slot.c */ #include #include

int x[3]; long kin;

int kekka();

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

srand( getpid() ); /* 设定随机数的种子数 */

signal( SIGKILL , kekka ); /* 当Ctrl+C按下时,执行kekka函数 */ kin = atoi( argv[1] ); /* 取得赌注数目 */

printf(press Ctrl+C to stop maching !\\n); while(1) {

x[0]=rand(); x[1]=rand(); x[2]=rand();

printf(%d %d %d\\n,x[0],x[1],x[2]); fflush( stdout ); }

return 0; }

int kekka() {

if( x[0]==x[1] && x[1]==x[2] )

printf(Great , you won %d \\n , kin*3000); else

printf(You lost %d\\n,kin);

exit(0); /* 游戏结束。退出程序 */ }

执行方法: %./slot 100

执行后。画面上会出现一排排的数字。当你按下Ctrl+C的时候,程序得到信号,跳转至kekka()函数入,判断随机数。然后退出程序。

这里有这样一个新函数。是我们在UNIX程序设计中时常用得到的。

#include

int ( *signal( int sig , void (*func()) ))(); 返回值: 成功时:进程中断地址 错误时:SIG_ERR

这个函数挺不好懂呵。解释解释。它的意思是,当收到SIG这个信号时,跳转至func()这个函数处继续执行。

int sig这个参数其实好办。下面我们会给出一个表。将其所有的参数一并列出。这是在头文件中#define的,代表各种不同的信号。 void ( * func() )

这个参数是一个函数指针。意思是在SIG信号被传给进程后,所要执行的部分。 此外,func()这个参数还可以为如下值: SIG_DEL 系统的默认动作 SIG_IGN 忽略这个信号。

signal作用只有一次,当一个信号发生,触发signal动作的之后,signal就不起作用了。

比方说,在上例中,如果你把所有的exit(0)全去掉(不退出程序),程序会进入无限循环中。你按一次Ctrl+C,signal执行一次,显示出结果。然后继续循环,生成随机数,输出。你再按Ctrl+C,signal就不好使了。

如果需要重复使用signal()函数,可以考虑在signal调用的动作函数中再加一个signal,比方说在上例的程序中再加一个 signal( SIGKILL , kekka );

加了signal这个函数后,整个程序如果没收到信号,则正常执行。否则跳转至signal中指定的func()函数处继续。

当然,我们不可能,也没有必要去为每一个信号指定一个动作。当未指定动作的信号发生的时候,系统会执行默认的动作。比方说我们知道:当Ctrl+C按下的时候,正常默认的动作是结束程序。但是,Ctrl+C按下时,发生的信号是SIGKILL,如果你为SIGKILL这个信号指定了一个动作的话,系统将去执行你指定的这个动作,而不管原来默认的了。 打个比方让大家更容易懂一些:

比方说:你在睡午觉。突然来了一个美女(帅哥)(Ctrl+C)让你陪她/他去逛街购物共进晚餐……(此处删去若干字),你正常的默认的动作是马上起来陪她出去玩(程序中止)。但是你妈说不许去,你妈说你得在家擦窗户,你只好留在家擦窗户(signal()指定的动作)。擦完窗户之后你可以选择陪美女去逛街(默认动作,Ctrl+C的埸合是退出程序,即上例程序中的exit(0)),可以选择继续睡觉(回到原来中断的地方继续执行,上例程序中如果没有exit(0),便会回到中断处继续执行)。 (大哥。打个比方嘛。干嘛拿臭鸡蛋砸我……)

signal种类非常多,在此不一一列出。

使用这个函数,你可以防止用户按下Ctrl+C结束程序。还可以做很多其它的事——只有你想不到的,没有C做不到的。

注意:根据UNIX系统的不同,signal的定义是不一样的。比方说,有的老式UNIX工作站上SIGINT是按下del键后发生的信号,而有些机型上刚是按下Ctrl+Z发生的。在使用时要注意。

第八章:向其它进程传递信号

上一章,我们简单地说了一下信号。信号不仅仅可以在本进程内使用,还可以向其它的进程传递。确切地说,一般情况下,一个进程收到的信号绝大部分是从系统的INIT传来的。而INIT也是一个进程。

用过UNIX或者LINUX的朋友大概都知道,UNIX系的操作系统里,有一个kill命令。如果你的一个进程无法中止,可以使用kill命令强行干掉它。 %kill mypro

我们自己也可以做个简单的kill命令。

/* nkill.c */ #include #include #include

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

pid_t pid;

if( argc != 2 ) // 检查命令行参数个数 {

fprintf( stderr , Usage : %s PID \\n , argv[0] ); exit(1); }

pid = atol( argv[1] );

if( kill( pid , SIGKILL )!=0 ) // 向pid这个进程传送一个SIGKILL信号 {

fprintf( stderr , kill failed\\n ); }

return 0; }

执行例:

%sleep 300 & (后台睡眠300秒) [1] 520 %nkill 520

[1] + Killed sleep 300

你用自己写的程序杀死了一个sleep进程。没事。杀了就杀了吧。留着也是垃圾…… 说明一下,众所周知,UNIX是非常注意用户的权限的。所以,如果你向你自己生成的进程发送SIGKILL的话,这个进程会中止。如果你是向别的(你没有写权限的)进程发送SIGKILL的话,除非那个进程允许你动它,否则你发了也是白发。打个不恰当的比较下流一些的比方:如果你要求亲一下你自己老婆的话(你有“亲”的权限),你会如愿以偿。但是如果你想亲一下别人的老婆的话(你没有“亲”的权限),除非他及她同意,否则……呵呵。你死定了。

所以,执行上面的程序的时候,你必须保证你有权限关掉那个进程。可不是说你ps -ef然后随便挑一个进程就能关的。要不那黑客也太好当了。

几乎是咱们的老规矩了:先写个程序,然后解释这个程序,说说其中新出现的函数。这回还照旧吧。

大家看到了。这里新出来一个kill()函数。解释如下:

#include #include

int kill( pid_t pid , int sig ); 返回值: 成功时:0 失败时:-1

这个函数是向进程ID(PID)为pid的进程传送一个sig信号。

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库UNIX系统程序设计教程(4)在线全文阅读。

UNIX系统程序设计教程(4).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/zonghe/474333.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: