【Linux】进程控制!!!

在linux里面常用的调度算法是时间片轮转法,即每一个进程分为很多的块,每一块都只能占用CPU固定的时间,当时间到,这个进程就必须放弃对CPU的使用权限。然后CPU去执行下一个进程。
在使用fork()函数创建一个子进程的时候,父进程和子进程执行的先后顺序是不确定的,所以子进程和父进程执行行为先后次序是不确定的。但是在除开使用fork()函数的同时也可以使用vfork()来创建进程,vfork()在创建进程的时候,必须是在子进程执行完之后再去执行父进程。在fork()创建进程的时候采用的是写实拷贝技术,但是使用vfork()函数的时候即使写时也不拷贝,即在改变子进程的同时也改变了父进程的数据。也因此,在使用vfork()创建进程的时候会出现一些意想不到的事情。

进程等待:
必要性:在使用多进程的时候,父进程需要知道子进程的退出信息,同时也需要回收子进程的资源,以及子进程的死亡信息。

进程等待的方法:
pid_t wait(int * status);
如果wait函数正常返回,则返回死亡子进程的ID,其中status里面保存的是子进程退出的基本信息。如果wait函数调用失败则返回-1。

例如:


#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>

int main()
{
    pid_t pid;
    printf("begin fork()!\n");
    pid = fork();
    if(pid == -1)
        perror("fork():");
    if(pid == 0)
    {
        printf("I'm child!\n");
        sleep(5);
    }
    else
    {
        int status;
        wait(&status);
        printf("wait end!\n");
    }
    return 0;
}

这里写图片描述

在输出I'm child!之后睡眠5秒之后再输出wait end!

在这个程序里面,当使用fork()函数之后,父进程和子进程同时存在,但是在父进程里面使用了wait函数,这时候在子进程没有退出之前,父进程一直在wait函数地方等待,直到子进程在执行完之后再退出,这时候wait函数返回,父进程开始执行下面的代码。

pid_t waitpid(pid_t pid,int* status,int pation);

pid
- pid = -1 表示任意一个子进程退出,则返回
- pid >0 表示等待和pid相同的ID进程退出则返回。
status

  • WIFEXITED : 判断自己成是否是正常退出
  • WEXITSTATUS:如果返回statu>0,则提取子进程的退出码

pation
- WNOHANG:如果指定子进程没有返回,则返回0,如果正常返回则返回指定子进程的ID。在程序执行的过程中不等待。
例如:


int main()
{
    pid_t r;
    pid_t pid;
    int status;
    pid = fork();
    if(pid == -1)
        perror("fork():");
    else if(pid == 0)
    {
            printf("hehe\n");
    }
    else
    {
        r = wait(&status);
        printf("%d\n",WEXITSTATUS(status));
    }
}

waitpid函数是在指定子进程退出之后waitpid函数在返回,使用waitpid函数就可以实现指定进程死亡之后,在执行父进程。

在子进程没有执行结束,调用wait/waitpid函数会处于阻塞状态。若子进程正常返回,则wait/waitpid函数正常返回,若不存在子进程或者指定子进程,则wait/waitpid函数立即报错。

若果子进程存在并且子进程退出,则wait函数正常返回,回收子进程的资源,获得子进程的退出信息。
若子进程处于运行状态,则wait函数处于阻塞状态,等待子进程退出。
若子进程不存在,wait函数立即报错。

利用进程等待实现myshell:


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<ctype.h>
#include<string.h>

void  do_action (char* argv[])
{
    if(fork() == 0)
        execvp(argv[0],argv);
    else
        wait(NULL);
}


void do_pose(char *buf)          //将输入的字符串拆分
{
    int i=0;
    int status = 0;
    char * argv[8];
    int argc = 0;
    for(;buf[i] != '\0';i++)
    {
        if(status == 0 && !isspace(buf[i]))
        {
            argv[argc++] = buf + i;
            status = 1;
        }
        else if(isspace(buf[i]))
        {
            buf[i] = 0;
            status = 0;
        }
    }
    argv[argc] = NULL;
    do_action(argv);
}


int main()
{
    char buf[1024];
    while(1)
    {
        printf(">:");
        scanf("%[^\n]%*c",buf);
        if(strcmp(buf,"exit")==0)
            exit(0);
        do_pose(buf);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值