Linux系统编程-进程

进程创建和结束

所有的进程都是由其他进程创建(除了 pid 为 0 号的 idle 进程),pid 号为 1 的 init 进程是系统启动后运行的第一个进程,是所有进程的父进程,init 进程会初始化一部分系统服务,创建其他进程。

子进程结束后,它的父进程要回收它的资源,否则就会成为僵尸进程 。

如果父进程先结束,子进程会被 init 进程收养,称为孤儿进程。

“ps -el”查看进程状态 PID 为进程号,PPID 为此进程的父进程号

getpid() 

getpid():获取进程 PID, 
    #include  
    #include  
    pid_t getpid(void);//获取此进程 
    PID pid_t getppid(void);//获取父进程 PID 
返回值为 PID 号。

 fork()

fork():系统调用,创建一个进程, 
#include  pid_t fork(void); 
//调用成功父进程返回子进程号,子进程返回 0,失败返回-1。
/*第一次调用 fork()进程 2531 创建子进程 2532;第二次 fork(),进程 2531 创建子进程 2533, 进程 2532 创建 2534*/
#include  
#include  
#include  
int main(int argc, const char *argv[]) 
{ 
    pid_t pid; 
    int i; 
    for(i=0;i<2;i++)
    { 
        pid=fork(); 
        if(pid>0)
        { 
            printf("进程%d\n",getpid()); 
        }else if(pid == 0)
        { 
            printf("进程%d\n",getpid()); 
        } 
    }
    return 0; 
}

exit() 

exit():进程终止可使用, 
#include  
void exit(int status);
/*函数功能:调用各终止处理程序进行清理退出,通过参数保存退出状态,调用_exit 进入内核态,向父进程发送信号 SIGCHLD,子进程终止。 参数含义:退出状态,如 EXIT_SUCCESS 和 EXIT_FAILURE。*/

 wait(),waitpid()

wait(),waitpid():回收子进程可使用, 
#include  
#include  
pid_t wait(int *status); 
pid_t waitpid(pid_t pid, int *status, int options); 
参数含义: 
/*status:
子进程的退出状态,可以用以下几个宏判断状态: 
WIFEXITED(status) //判断子进程是否正常结束 
WEXITSTATUS(status) //获取子进程返回值,1为正常,0为失败
WIFSIGNALED(status) //判断子进程是否被信号结束 
WTERMSIG(status) //获取结束子进程的信号类型 
/*
pid:
waitpid()中的参数,
pid=-1 时,表示等待任一子进程退出,
pid > 0 等待 pid 号子进程退出。 
options:
waitpid()中的参数,控制 waitpid()。 
返回值:若成功则为进程 ID,若出错则为-1 。
*/
#include  
#include  
#include  
#include  
void exit_status(pid_t p ,int s); 
int main(int argc, const char *argv[]) 
{ 
    pid_t pid,spid; 
    int s_son=-1; 
    pid = fork(); 
    if(pid<0)
    {
        perror("fork"); return 1; 
    }else if(pid == 0)
    { 
        printf("子进程 %d\n",getpid()); 
        sleep(1); 
        exit(EXIT_FAILURE); 
        //exit(EXIT_SUCCESS);//返回 0 
    }else if(pid >0)
    { 
        printf("父进程 %d\n",getpid()); 
        //sleep(1);//等待子进程退出 
        spid = wait(&s_son);//获取子进程退出状态 
        exit_status(spid,WEXITSTATUS(s_son));//打印 
    }
    return 0; 
}
/** 打印退出状态 */ 
void exit_status(pid_t p ,int s) 
{ 
    switch (s)
    { 
        case 0: printf("子进程--%d--退出状态: EXIT_SUCCESS\n",p); break; 
        case 1: printf("子进程--%d--退出状态: EXIT_FAILURE\n",p); break; 
        default: printf("other\n"); break; 
    } 
}

exec 函数族

用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序,该子进程被新的程序 替换,改变地址空间,进程映像和一些属性,但是 pid 号不变。
execve():
#include  
int execve(const char *filename, char *const argv[], char *const envp[]); 
/*
参数含义: 
filename:路径名,表示载入进程空间的新程序路径。 
argv[]:命令行参数,argv[0]为命令名。 
envp[]:新程序的环境变量。 
返回值:成功时不会返回,使用时不用检查返回值,可通过 errno 检查。 
以下函数都是根据 execve 实现: 
*/
int execl(const char *path, const char *arg, .../* (char *) NULL */); 
int execlp(const char *file, const char *arg, .../* (char *) NULL */); 
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */); 
int execv(const char *path, char *const argv[]); 
int execvp(const char *file, char *const argv[]); 
int execvpe(const char *file, char *const argv[],char *const envp[]);

#include  
#include  
#include  
#include 

void exit_status(pid_t p ,int s); 

int main(int argc, const char *argv[]) 
{ 
    pid_t pid,spid; 
    int s_son=-1; 
    pid = fork(); 
    if(pid<0)
    { 
        perror("fork"); 
        return 1; 
    }else if(pid == 0)
    { 
        printf("子进程 %d\n",getpid()); 
        if(-1 == execl("/bin/ls","ls","./",NULL))//ls 进程替换子进程 
        { 
            perror("execl"); 
            exit(EXIT_FAILURE); 
        }
        exit(EXIT_SUCCESS);//返回 0 
    }
    else if(pid >0)
    { 
        printf("父进程 %d\n",getpid()); 
        spid = wait(&s_son);//获取子进程退出状态 								 
        exit_status(spid,WEXITSTATUS(s_son));//打印 
    }while(1) 
    { 
        printf("hello\n"); 
        sleep(2); 
    }
    return 0; 
}/** 打印退出状态 */ 
void exit_status(pid_t p ,int s)
{ 
        switch (s)
     {
     	case 0: printf("子进程--%d--退出状态: EXIT_SUCCESS\n",p); break; 
     	case 1: printf("子进程--%d--退出状态: EXIT_FAILURE\n",p); break; 
     	default: printf("other\n"); break; 
     } 
 }

守护进程

1.什么是守护进程? 守护进程运行在后台,不跟任何控制终端关联。

2.怎么创建一个守护进程?

有俩个基本要求:1.必须作为我们init进程的子进程⒉.不跟控制终端交互。

1.使用fork函数创建一个新的进程,然后让父进程使用exit函数直接退出(必须要的)

2.调用setsid函数。(必须要的)

3.调用chdir函数,将当前的工作日录改成根目录,增强程序的健壮性。(不是必须要的)

4.重设我们umask文件掩码,增强程序的健壮性和灵活性(不是必须要的)

5.关闭文件描述符,节省资源(不是必须要的)

6.执行我们需要执行的代码(必须要的)

#include 
#include 
#include 
#include 
#include 

int main(vold)
{
    pid_t pid;
    //步骤一:创建一个新的进程
    pid = fork();
    /父进程直接退出
    if(pid > 0)
    {
        exit(0);
    }
    if(pld == 0)
    {
        //步骤2:调用setsid函数摆脱控制终端
        setsid();
        //步骤3:更改工作目录
        chdir("/");
        //步骤4:重新设置umask文件掩码
        umask(0);
        //步骤5:关闭012三个文件描述符
        close(0);
        close(1);
        close(2);
        //步骤6:执行我们要执行的代码
        while(1)
        {
        }
    }
    return 0;
}

你可能感兴趣的:(C语言,linux,学习,ubuntu,linux)