当前位置:操作系统 > Unix/Linux >>

UNIX学习之UNIX编程资料大收集二

当命令行参数的个数不为1时,程序使用fork系统调用产生一个子进程。子进程通过系统调用getpid获得自己的进程标识符,然后调用exec执行命令行中用户提交的命令,如果exec执行失败,则子进程调用exit(5)终止。父进程使用wait系统调用等待子进程暂停或终止,然后输出从wait中返回的信息。下面以三种方式执行该程序:

  1〕 不带命令行参数

  % ./feew

  pid=-1, H_stat=0, L_stat=0

  %

  不产生子进程,从运行结果来看,当无子进程时,wait的返回值为-1。

  2〕 带命令行参数,参数为合法的可执行命令

  % ./feew /bin/date

  Child pid = 1725

  1998年 2月16日(星期一) 15时59分14秒 CST

  pid=1725, H_stat=0, L_stat=0

  %

  产生子进程。子进程输出其进程标识符后,再调用exec执行从命令行中提交的命令(/bin/date),同时父进程等待子进程暂停或终止,然后输出从wait中得到的信息:子进程标识符或状态参数stat的高八位、低八位的内容。从中可以看到:子进程因调用一个隐含的exit(0)而终止,终止时传给父进程的值为0。

  3〕 带命令行参数,但参数不合法

  %./feew /etc/shudown

  Child pid = 1760

  /etc/shutdown: 只有超级用户(root)能运行 /etc/shutdown。

  pid=1760, H_stat=2, L_stat=0

  %

  子进程创建成功。但由于以普通用户的身份执行/etc/shutdown,因此exec失败,尔后调用exit(5)而终止;父进程调用wait得到返回值:子进程号和状态参数stat的高八位、低八位的内容。从执行结果可以看出:子进程因调用exit(5)而终止,终止时传给父进程的值为5。

  5.3 进程管理

  进程管理包括的面很广,诸如进程的用户标识符管理、进程标识符管理等。进程的用户标识符有两个:实际用户标识符(real user

  id)和有效用户标识符(effective user id),其对应的组标识符分别称为实际组标识符(real group

  id)和有效组标识符(effective groud

  id)。一般而言,进程的实际用户标识符为运行该进程的用户标识符,通常只用于系统记帐,其他功能由有效用户标识符来完成,如用有效用户标识符来完成对新创建文件赋予属性关系、检查文件的存取权限和利用kill系统调用向进程发送信号的权限。一般情况下,一进程的有效用户标识符和实际用户标识符是相等的,但系统允许改变进程的有效用户标识符。

  1. 进程的用户标识符管理

  UNIX系统提供了一组系统调用来管理进程的用户标识符,它们的使用形式是:

  #include <sys/types.h>

  #include <unistd.h>

  uid_t getuid (void);

  uid_t geteuid (void);

  gid_t getgid (void);

  gid_t getegid (void);

  int setuid(uid_t uid);

  int setgid(gid_t gid);

  说明:前四个系统调用没有参数,分别返回调用进程的实际用户标识符、有效用户标识符、

  实际用户组标识符和有效组标识符。这些系统调用的执行总能获得成功,不会发生任何错误。系统调用setuid和setgid用于设置进程的实际用户(组)标识符和有效用户(组)标识符,如调用进程的有效用户标识符是超级用户标识符,则将调用的进程实际用户(组)标识符和有效用户(组)标识符设置为uid或gid;如调用进程的有效用户标识符不是超级用户标识符,但其实际用户(组)标识符等于uid或gid时,则其有效用户(组)标识符被设置为uid或gid;否则setuid或setgid调用失败。系统调用setuid或setgid调用成功时返回0,失败时返回-1。

  2. 进程标识符管理

  UNIX系统使用进程标识符来管理当前系统中的进程。为对具有某类似特性的进程统一管理,系统又引入了进程组的概念,以组标识符来区别进程是否同组。进程的组标识符是从父进程继承下来的,所以,通常进程的组标识符就是和它相关联的注册进程的标识符。进程的标识符是由系统为之分配的,不能被修改;组标识符可通过setpgrp系统调用修改。

  相关系统调用的格式如下:

  #include <sys/types.h>

  #include <unistd.h>

  pid_t getpid(void);

  pid_t getpgrp(void);

  pid_t getppid(void);

  pid_t getpgid(pid_t pid);

  说明:前三个系统调用分别返回调用进程的进程标识符、进程组标识符和其父进程标识符。它们总能成功地返回。第四个调用置进程组标识符,它将调用进程的进程组标识符改为调用进程的进程标识符,使其成为进程组首进程,并返回这一新的进程组标识符。

  下面我们来看一个实例:

  /* setuid.c */

  main(argc, argv)

  int argc;

  char *argv[];

  {

  int ret, uid;

  uid = atoi(argv[1]);

  printf("Before uid=%d, euid=%d\n", getuid(), geteuid());

  ret = setuid(uid);

  printf("After uid=%d, euid=%d\n", getuid(), geteuid());

  printf("ret = %d\n", ret);

  }

  下面分三种情况讨论该程序的执行:

  1、 如果执行该程序的用户为超级用户,则只要命令行所给的用户标识符大于0,无论所给的用户标识符是否存在,执行总能成功。

  #./setuid 3434

  Before uid=0, euid=0

  After uid=3434, euid=3434

  ret = 0

  #

  结果分析:将进程的实际和有效用户标识符均改为3434。

  2、 如果执行该程序的用户为一般用户,用id命令得到用户uid和gid后,再调用该程序,过程如下:

  %id

  uid=1111(yds) gid=20(user)

  %./setuid 3434

  Before uid=1111, euid=1111

  After uid=1111, euid=1111

  ret = -1

  %./setuid 1111

  Before uid=1111, euid=1111

  After uid=1111, euid=1111

  ret = 0

  %

  结果分析:当命令行参数为1111时,setuid执行成功,因为用户的uid就是1111。

  值得注意的是:注册程序login

  是个典型的setuid系统调用程序,login进程的有效用户是超级用户,该进程在建立用户的Shell进程前,调用setuid将实际和有效用户标识符调整为注册用户的用户实际和有效标识符。

  第六章 设备输入/输出控制

  6.1 概述

  UNIX将设备看成文件,这是UNIX的一大特色。这里需要介绍一个设备号的概念。设备特别文件与两个设备号有关-主设备号和次设备号。主设备号告诉操作系统,当涉及文件名时,将使用哪种设备类型。对于每一种类型的设备都有一段驻留在操作系统中的程序代码,以控制相应类型的设备,这段代码被称为"设备驱动程序"。次设备号被传递给设备驱动程序,这个号码用来决定使用哪种物理设备。例如,决定在一块多重驱动控制卡上,哪个磁盘驱动器将被访问,以及该磁盘驱动器中哪一部分将被使用;或者,当一个磁盘驱动器所请求的操作已经完成后,应该被恢复原状。几个设备(如同类型的磁盘驱动器)可以用同一个主设备号,但它们将有不同的次设备号。看下面的例子:

  %ls -l /dev/ttyq*

  crw--w---- 2 yds user 15, 1 2月 17日 09时03分 ttyq1

  crw--w---- 2 yds user 15, 14 2月 16日 17时00分 ttyq14

  %

  上例中15是主设备号,1和14是次设备号。

  用户可以使用系统提供的统一而且独立于设备的界面-对文件进行操作的系统调用来操作设备,而没有必要涉及设备的具体细节。大部分对文件进行操作的系统调用对它们仍起作用,例如,用open打开设备,用read/write对设备进行读/写,设备操作完成后,用close关闭设备。但有的系统调用在对设备文件进行操作时,其功效有所不同。如create及open的创建方式都不能创建设备文件。

  6.2 设备输入/输出控制-ioctl系统调用

  ioctl是UNIX系统专门提供的用于设备控制的系统调用。该系统调用与设备类型(即主设备号)相关。不同的设备,系统提供了不同的控制命令。

  ioctl的调用格式是:

  ioctl(int fd, int cmd,arg…)

  说明:参数fd是一设备文件的文件描述字,cmd是控制命令,它与设备相关,不同类型的设备有不同的控制命令。参数arg没有固定的数据结构,它随cmd的不同而不同。

  第七章 高级编程

  7.1 处理信号

  信号是UNIX进程间最基本的通讯手段,主要作用是实现进程间异步事件的通讯。信号是传送到进程的"软中断",它通知进程在它们的环境中出现了非正常事件。进程接收到信号后要进行处理,处理方式为以下四种之一:

  (1)缺省方式(SIG_DFL):这是进程对信号的一般处理方式,在无特殊情况下,进程在接收到信号后将终止执行。有一些信号,在终止进程运行前需将终止进程的正文段、数据段、user结构和栈段内容写到当前目录的core文
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,