【进程控制】上

笔记仅归纳进程常用函数,具体函数用法看man手册

1、进程标识符pid

类型pid_t
查看进程命令 ps

#include <unistd.h>
pid_t  getpid(void);
			     // 返回值:调用进程的进程ID
pid_t  getppid(void);
				 // 返回值:调用进程的父进程ID

2、进程的产生

fork() --->一个现有的进程可以调用fork函数创建一个新进程
#include <unistd.h>
pid _t  fork(void);
			//返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1

具体查看man手册: man fork
注意理解关键字:duplicating,意味着拷贝,克隆,一模一样等含义

fork 后父子进程的区别:fork 的返回值不一样,pid不同,ppid也不同,未决信号和文件锁不继承,资源利用量清0
init 进程:1号,是所有进程的祖先进程
调度器的调度策略来决定哪个进程先运行
fflush() 的重要性(在fork之前要先fflush(NULL)刷新一下流)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    pid_t pid;

    printf("[%d]:Befin!\n",getpid());  //先打印一遍父进程

    fflish(NULL);  /*!!!在fork()之前刷新所有打开的流*/

    pid = fork();  //创建子进程
    if(pid < 0)    //创建失败
    {
        perror("fork()");
        exit(1);
    }

    if(pid == 0)   //child,创建子进程成功,执行子进程的任务
    {
        printf("[%d]:Child is working!\n",getpid());
    }
    else          //parent  ,即pid > 0,否则执行父进程
    {
        printf("[%d]:Parent is working!\n",getpid());
    }

    printf("[%d]:End \n",getpid());

    //getchar();

    exit(0);

}
vfork();函数的调用序列和返回值fork相同,但两者的语义不同
		用来创建一个新进程,而该新进程的目的是exec一个新程序

区别:

  1. vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会引用该地址空间。不过在子进程调用exec或exit之前,它在父进程的空间中运行。
  2. vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行,当子进程调用这两个函数中的任意一个时,父进程会恢复运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)

3、进程的消亡及释放资源

#include <sys/types.h>
#include <sys/wait.h> 
 wait();
 waitpid();  
		 //两个函数返回值:若成功,则返回进程ID;若出错,则返回0或-1

 waitid();
 
 wait3();
 wait4();
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>  

#define LEFT   30000000
#define RIGHT  30000200

int main()
{
    int i,j,mark;
    pid_t pid;
    for(i = LEFT; i <= RIGHT; i++)  //parent
    {
        pid = fork();
        if(pid < 0)
        {
            perror("fork()");
            exit(1);
        }

        if(pid == 0)   //child
        {
            mark = 1;
            for(j = 2; j < i/2; j++)
            {
                if(i % j == 0)
                {
                    mark = 0;
                    break;
                }
            }
            if(mark)
            {
                printf("%d is a primer\n",i);
            }
            exit(0);  /*一定要有退出,否则每一个子进程执行完会充当父进程继续创建子进程*/
        }

    }

    for(i = LEFT; i < RIGHT; i++)
    {
        wait(NULL); //给子进程消亡并释放资源
    }

    exit(0);
}

4、exec 函数族

exec() -->当进程调用一种exec函数时,该进程执行的程序完全被替代为新程序,而新程序则从main函数开始执行

#include <unistd.h>
int  execl   (const char *pathname,  const char *arg0, ..../* NULL */);
int  execv  (const char *pathname,  char *const arg[ ]);
int  execle (const char *pathname,  const char *arg0,  ..../* NULL,  char *const envp[ ] */);
int  execve(const char *pathname,  char *const arg[ ], char *const envp[ ]);
               //这四个函数取路径名作为参数
int  execlp (const char *filename,  const char *arg0, ..../* NULL */);
int  execvp(const char *filename,  char *const argv[ ]));
		     //这两个函数取文件名作为参数
  1. 如果filename中包含/, 则就将其视为路径名
  2. 否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件。其中PATH变量包含了一张目录表(称为路径前缀)目录之间用冒号:分隔。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    puts("Begin");

    fflush(NULL);  /*!!! exec()之前要用fflush(NULL)刷新一下流*/
				  //可以分别将结果在终端输出和重定向输出到文件,来看没有刷新流时的区别
    execl("/bin/date","date","+%s",NULL);
    perror("execl()");
    exit(1);

    puts("End");

    exit(0);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值