linux编程主题之进程

  首先,关于进程的三个用户ID。实际用户ID、有效用户ID、保存设置用户ID。

    实际用户ID:进程执行者的ID。

    有效用户ID:如果进程对应的程序文件设置了设置用户ID,则为程序文件所有者的ID。

    保存设置用户ID:有效用户ID的副本。

  这里还有设置用户ID的概念,设置用户ID是针对程序文件来说的,设置了设置用户ID的程序文件,在执行这个文件时,进程的有效用户ID与保存设置用户ID都为程序文件所有者的ID,这时实际用户ID和有效用户ID就不一定相等了。

  每个进程都有一个非负整型表示的唯一进程ID,返回进程ID的函数:

      pid_t getpid(void);           //调用进程的进程ID

      pid_t getppid(void);         //调用进程的父进程ID

      uid_t getuid(void);           //调用进程的实际用户ID

      uid_t geteuid(void);         //调用进程的有效用户ID

      gid_t getgid(void);           //调用进程的实际组ID

      gid_t getegid(void);         //调用进程的有效组ID

  一个现有进程可以调用fork函数创建一个新进程,函数为:

      pid_t fork(void);

    fork函数被调用一次,但返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。子进程和父进程继续执行fork调用之后的指令。

    使fork失败的原因主要有两个:系统中已经有了太多的进程、该实际用户ID的进程总数超过了系统限制。

  父进程获取子进程的终止状态的函数:

       pid_t wait(int *statloc);

       pid_t waitpid(pid_t pid, int *statloc, int options);

    waitpid可等待一个特定的进程,而wait则返回任一终止子进程的状态;waitpid提供了一个wait的非阻塞版本;waitpid支持作业控制。

  这里有一个僵死进程的概念:在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显示忽略该信号,则子进程成为僵死进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵死进程。补救方法是杀死僵死进程的父进程,这样僵死进程成为“孤儿进程”,过继给1号进程init,init始终会负责清理僵死进程。     

  用fork可以创建新进程,用exec可以执行新程序。其中execl函数用的比较多。

      int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );

  更改用户ID和组ID

      int setuid(uid_t uid);

      int setgid(uid_t gid);

    这里要注意的是:若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID、以及保存的设置用户ID设置为uid。若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid,不改变实际用户ID和保存的设置用户ID。如果上面两个条件都不满足,则将errno设置为EPERM,并返回-1。

  在程序中执行一个命令字符串很方便

     int system(const char *cmdstring);

  进程间通信有很多种方法,以下是最常见的两种方法:

  1、管道

      管道是由pipe函数创建的,一般是半双工的,只能在具有公共祖先的进程之间使用。

      int pipe(int filedes[2]);

        filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。

      常见的操作是创建一个管道连接到另一个进程,然后读其输出或向其输入端发送数据,为此,标准I/O库提供了两个函数popen和pclose。

      FILE *popen(const char *cmdstring, const char *type);

      int pclose(FILE *fp);

  2、FIFO(命名管道)

      通过FIFO,不相关的进程也能交换数据。

      int mkfifo(const char *pathname, mode_t mode);

      一旦已经用mkfifo创建了一个FIFO,就可用open打开它。

  另外,消息队列、信号量和共享存储器也是常见的进程间通信的方法,这里就不一一介绍了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值