首页 > 系统运维 > 进程

进程

2017年1月12日 发表评论 阅读评论
标 签:

1、 什么是进程

进程是一个执行的过程
进程是一段独立的程序,在某个数据集合上的一次运行的过程
./a.out(回车)产生了一个进程

2、进程和程序的区别和联系

什么是程序----程序是写好的代码,是一个文件,可以保存
进程是不能保存的,程序是可以保存的
进程是动态的,程序是静态的
程序经过编译运行产生进程
进程是操作系统分配资源的最小单位  

了解
init—-PID == 1
操作系统第一个进程 始祖

进程类型:

交互进程
批处理进程
守护进程

理解进程状态

运行态 就绪态 等待态

3、理解fork

fork用来创建进程
在程序中使用fork成功后,会有父进程和子进程
可以通过fork的返回值来区分父子进程
我们不确定CPU先调度哪一个
getpid()的返回值是调用它的进程的进程号
getppid()的返回值是调用它的进程B的父进程A的进程号
结论:fork在创建子进程成功时,给父进程返回的值,是创建好的那个子进程的PID
fork给子进程返回的值是0

fork.c

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

//创建进程,父子进程执行相同的打印语句
int main()
{
    pid_t pid = -1;

    pid = fork();//create process
    if (pid < 0)
    {
        perror("fork error");
        return -1;
    }
    if (0 == pid)
    {
        sleep(10);
        printf("child process, %d\r\n", getpid());
        printf("%d\r\n", getppid());
    }   
    else 
    {
        printf("parent process, %d\r\n", pid);
        printf("%d\r\n", getpid());
    }
    printf("after fork\r\n");
    return 0;
}

4、进程的退出

1、程序运行结束  --------main中的return
2、收到信号(中断)
3、程序中调用进程退出的函数exit,_exit
exit在进程退出时,回收资源             

僵尸进程——自己写代码时,需要避免出现僵尸进程,父进程使用wait/waitpid可以避免产生僵尸进程
孤儿进程——父进程先结束,子进程被称为是孤儿进程。孤儿进程会由init进程收养  
#include <stdio.h>
#include <stdlib.h>//exit
#include <unistd.h>//_exit

//exit,_exit是进程退出函数
int main()
{
    int i = 3;
    while (i--)
    {
        if (1 == i)
        {
            _exit(0);
        }
    }

    printf("break from while\r\n");

    return 0;
}

5、等待子进程结束

wait
waitpid
子进程在退出时调用了 exit(10)
父进程回收资源,想要获得子进程退出状态 wait()

pid_t  wait(int  * status);   // 调用它时,需要传参
pid_t  waitpid(pid_t  pid,  int  * status,  int  options);    //一般用的比较多的是:waitpid ( pid, &status, WNOHANG);----非阻塞
得到的子进程退出状态存放在status中,用下面的两个宏来取出退出原因和状态

if ( WIFEXITED ( status ) )
{
printf(“%d exit normall,status = %d\r\n”, ret, WEXTSTATUS(status));
}

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

//创建进程,父子进程执行相同的打印语句
int main()
{
    pid_t pid = -1;

    pid = fork();//create process
    if (pid < 0)
    {
        perror("fork error");
        return -1;
    }
    if (0 == pid)
    {
        sleep(10);
        printf("child process, %d\r\n", getpid());
        exit(10);
    }   
    else 
    {
        int status = 0;
        int ret = 0;
        do {
        ret = waitpid(pid, &status, WNOHANG);
        printf("%d\r\n", getpid());

        printf("parent process, %d\r\n", pid);
        sleep(1);       
        }while(0 == ret);

        if (WIFEXITED(status))
        {
            printf("%d exit normall, status  = %d\r\n", ret, WEXITSTATUS(status));
        }
    }
    printf("after fork\r\n");
    return 0;
}

6、exec

exec函数族提供了一种在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段、和堆栈段。在执行完之后,原调用进程的内容除了进程号外,其他全部都被替换了。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

何时使用?

当进程认为自己不能再为系统和用户做任何贡献了就可以调用exec函数族中的函数,让自己执行新的程序。
当前目录: 可执行程序A    B(1,2,3)     
如果某个进程想同时执行另一个程序,它就可以调用fork函数创建子进程,然后在子进程中调用任何一个exec函数。这样看起来就好像通过执行应用程序而产生了一个新进程一样。

exec函数族使用注意点

在使用exec函数族时,一定要加上错误判断语句。
因为exec很容易执行失败,其中最常见的原因有:

①找不到文件或路径,此时errno被设置为ENOENT。

②数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT。

③没有对应可执行文件的运行权限,此时errno被设置为EACCES。  
#include <unistd.h>

int main()
{
    //execlp("ls", "ls", "-l", "/home/farsight", NULL);
    //execl("/bin/cat", "cat","wait2.c", NULL);

    char * argv[] = {"ls", "-l", "/mnt/hgfs", NULL};
    //execv("/bin/ls", argv);
    //execvp("ls", argv);

    char * envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
    //execle("/bin/ls", "ls", "/mnt/hgfs", NULL, envp);
    //execve("/bin/ls", argv, envp);

    char * cmd[] = {"hello" , NULL};
    execve("./hello", cmd, NULL);
    return 0;
}
作者:hang_1994 发表于2017/1/12 16:28:42 原文链接
阅读:13 评论:0 查看评论
分类: 系统运维 标签: