【从零开始的嵌入式生活】并发程序设计1——进程基本介绍(2)

简介: 【从零开始的嵌入式生活】并发程序设计1——进程基本介绍(2)

进程的回收

子进程结束时由父进程回收

孤儿进程由init进程回收

若没有及时回收会出现僵尸进程

进程回收 – wait

#include  <unistd.h>

pid_t wait(int *status);

#include  <unistd.h>
pid_t wait(int *status);


成功时返回回收的子进程的进程号;失败时返回EOF

若子进程没有结束,父进程一直阻塞

若有多个子进程,哪个先结束就先回收

status 指定保存子进程返回值和结束方式的地址

status为NULL表示直接释放子进程PCB,不接收返回值

相关示例在/study_qianrushi/5.proc/5.1base/wait.c

进程回收 – waitpid

#include  <unistd.h>
  pid_t waitpid(pid_t pid, int *status, int option);


成功时返回回收的子进程的pid或0;失败时返回EOF

pid可用于指定回收哪个子进程或任意子进程

status指定用于保存子进程返回值和结束方式的地址

option指定回收方式,0 或 WNOHANG

waitpid(pid, &status, 0);
waitpid(pid, &status, WNOHANG);
waitpid(-1, &status, 0);
waitpid(-1, &status, WNOHANG);


DXEC函数族

进程调用exec函数族执行某个程序

进程当前内容被指定的程序替换

实现让父子进程执行不同的程序


父进程创建子进程

子进程调用exec函数族

父进程不受影响

进程 – execl / execlp

#include  <unistd.h>
int execl(const char *path, const char *arg, …);
int execlp(const char *file, const char *arg, …);


成功时执行指定的程序;失败时返回EOF

path 执行的程序名称,包含路径

arg… 传递给执行的程序的参数列表

file 执行的程序的名称,在PATH中查找

#include <unistd.h>
#include <stdio.h>
int main(){
       if(execl("/bin/ls", "ls", "-a", "-l", "./", NULL) < 0){
               perror("execl");
       }
       printf("I ls current dircctory\n");
       return 0;
}


最后的一个参数一定是空!!!

execl之后的所有内容都会被替换掉,不会执行!!!!


进程 – execv / execvp

#include  <unistd.h>
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);


成功时执行指定的程序;失败时返回EOF

arg… 封装成指针数组的形式

与上面的程序类似,但是argv可以变化,更灵活一些,推荐使用。


system

#include  <stdlib.h>
int system(const char *command);


成功时返回命令command的返回值;失败时返回EOF

当前进程等待command执行结束后才继续执行


守护进程

守护进程(Daemon)是Linux三种进程类型之一

通常在系统启动时运行,系统关闭时结束

Linux系统中大量使用,很多服务程序以守护进程形式运行

特点:


始终在后台运行

独立于任何终端

周期性的执行某种任务或等待处理特定事件

Linux以会话(session)、进程组的方式管理进程

每个进程属于一个进程组

会话是一个或多个进程组的集合。通常用户打开一个终端时,系统会创建一个会话。所有通过该终端运行的进 程都属于这个会话

终端关闭时,所有相关进程会被结束


守护进程创建

1.创建子进程,父进程退出


if (fork() > 0)  {
       exit(0);
    }


子进程变成孤儿进程,被init进程收养

子进程在后台运行

2.子进程创建新会话


if (setsid() < 0)  {
exit(-1);
}


子进程成为新的会话组长

子进程脱离原先的终端

3.更改当前工作目录


chdir(“/”);
chdir(“/tmp”);


守护进程一直在后台运行,其工作目录不能被卸载

重新设定当前工作目录cwd

4.重设文件权限掩码


if (umask(0) < 0)  {
 exit(-1);
}


文件权限掩码设置为0

只影响当前进程

5.关闭打开的文件描述符


int  i;
for(i=0; i<getdtablesize(); i++) {
close(i);
}


关闭所有从父进程继承的打开文件

已脱离终端,stdin / stdout / stderr无法再使用

示例代码


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
int main(){
        pid_t pid;
        //first step
        pid = fork();
        if(pid < 0){
                perror("fork");
                return -1;
        }else if(pid > 0){
                exit(0);
        }
        //second step
        pid = setsid();
        if(pid == -1){
                perror("setsod");
                return -1;
        }
        //third step
        chdir("/");
        umask(0);
        int i;
        for(i = 0;i < 2;++i){
                close(i);
        }
        FILE *fp;
        time_t ctm;
        fp = fopen("1.log", "w");
        while(1){
                ctm = time(NULL);
                fputs(ctime(&ctm), fp);
                fflush(fp);
                sleep(1);
        }
        return 0;
}


写在最后

今天开启并发编程,我尽量一天一更,大家和我一起变强呀!明天开始进入线程专题!最后三连即可提高学习效率!!!


另外我在更新的就是算法笔记的一些例题笔记,这个系列是用于提高我的算法能力,如果有兴趣对算法领域感兴趣找不到合适的入门文章也可以追更,如果我更新的太慢了请大家点赞收藏,一键三连才能更有更新的动力呀0.0


相关文章
|
4月前
|
Shell
shell中并发执行多个进程
shell中并发执行多个进程
93 4
|
5月前
进程并发装饰器
进程并发装饰器
30 0
|
6月前
|
监控 Linux 调度
【CSAPP】进程 | 上下文切换 | 用户视角下的并发进程
【CSAPP】进程 | 上下文切换 | 用户视角下的并发进程
37 0
|
8天前
|
监控 安全 Java
一文讲明白Java中线程与进程、并发与并行、同步与异步
一文讲明白Java中线程与进程、并发与并行、同步与异步
7 1
|
2月前
|
消息中间件 监控 安全
【C/C++ 程序设计】Linux 进程管理 设计 获取进程信息 策略权衡
【C/C++ 程序设计】Linux 进程管理 设计 获取进程信息 策略权衡
70 0
|
6月前
|
存储 算法 Linux
【看表情包学Linux】进程优先级 | 查看系统进程 | 优先级修改 | 进程的切换 | 竞争性与独立性 | 并行并发的概念 | 环境变量
【看表情包学Linux】进程优先级 | 查看系统进程 | 优先级修改 | 进程的切换 | 竞争性与独立性 | 并行并发的概念 | 环境变量
59 0
|
2月前
|
存储 调度
进程的奥德赛:并发世界中的核心概念与动态管理
进程的奥德赛:并发世界中的核心概念与动态管理
38 2
|
7月前
|
Linux 程序员 数据安全/隐私保护
嵌入式 Linux进程间通信之信号量
嵌入式 Linux进程间通信之信号量
|
7月前
|
存储 算法 Linux
【Linux】进程优先级|进程并发概念|在vim中批量化注释
【Linux】进程优先级|进程并发概念|在vim中批量化注释