云计算百科
云计算领域专业知识百科平台

Linux软件编程-进程(2)及线程(1)

1.进程回收资源空间

(1)wait函数

头文件:

       #include <sys/types.h>
       #include <sys/wait.h>

函数接口:

       pid_t wait(int *wstatus);
       功能:阻塞等待回收子进程的资源空间
       参数:
               wstatus :保存子进程消亡状态的变量地址
                                 NULL:不保存子进程退出的状态
       返回值:
            成功:返回回收到的子进程的PID号
            失败:-1
        wait(NULL);

基本思想:

进程同步:允许父进程暂停执行,直到其子进程终止或改变状态

资源回收:确保子进程终止后其资源被正确释放(防止"僵尸进程")

状态获取:让父进程能够获取子进程的退出状态信息

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

int main(int argc, char const *argv[])
{
int *p = malloc(sizeof(int));
*p = 100;
pid_t pid = fork();

if(pid > 0)
{
int wstatus;
pid_t pidtmp = wait(NULL);
printf("pidtmp = %d\\n", pidtmp);
/*
if (WIFEXITED(wstatus))
{
printf("%d over normall, state : %d\\n", pidtmp, WEXITSTATUS(wstatus));
}
else if (WIFSIGNALED(wstatus))
{
printf("%d ober by signal,signal num = %d\\n", pidtmp, WTERMSIG(wstatus));
}
*/
while(1)
{
printf("ppid = %d, pid = %d, *p = %d\\n",getpid(), pid, *p);
sleep(1);
}

}
else if(0 == pid)
{
int i = 10;
while(i–)
{
printf("pid = %d, ppid = %d, *p = %d\\n", getpid(), getppid(), *p);
sleep(1);
}

}
else
{
perror("fork error");
exit(0);
}
return 0;
}

(2)waitpid函数

函数接口:

pid_t waitpid(pid_t pid, int *status, int options);
    功能:回收指定进程的资源
               和wait功能相似,比wait更灵活
    参数:
    pid:
        <-1 回收指定进程组内的任意子进程 (-100.等待GID=100的进程组中的任意子进程)
        -1 回收任意子进程,组内外
        0 回收和当前调用waitpid一个组的所有子进程,组内 
        > 0 回收指定ID的子进程
     status 子进程退出时候的状态,
              如果不关注退出状态用NULL;
     options 选项:
              0  表示回收过程会阻塞等待
            WNOHANG 表示非阻塞模式回收资源。
    返回值:

            成功 返回接收资源的子进程pid
            失败  -1
            设定为非阻塞且没有回收到子进程返回0 

(3)子进程资源空间回收策略

1. wait阻塞回收:一般情况下,父进程专门负责资源回收;
2. waitpid非阻塞方式回收:搭配轮询方式回收。
3. 不回收:子进程的任务需要一直执行
4. 异步回收:当子进程结束时通知父进程进行回收

2.  exec : 函数族

(1)基本概念

在一个进程里面执行另外一个文件(可执行文件):
本质:将文本去的指令代码替换成exec要执行的文件的指令。

算法思想:

不创建新进程:

与 fork() 不同,exec 不会创建新进程,只是替换当前进程的内容

参数传递多样性:

列表形式(execl, execlp, execle):以 NULL 结尾的可变参数列表

数组形式(execv, execvp, execvpe):通过字符串数组传递参数

函数关键特点
execl 路径+参数列表形式,需要完整路径
execlp 文件名+参数列表形式,会在 PATH 环境变量中查找可执行文件
execle 路径+参数列表+自定义环境变量形式
execv 路径+参数数组形式,需要完整路径
execvp 文件名+参数数组形式,会在 PATH 环境变量中查找可执行文件
execvpe 文件名+参数数组+自定义环境变量形式

(2)函数接口

 int execl(const char *path, const char *arg, …   /* (char  *) NULL */);
       参数:
               path:要执行的可执行文件的路径和名称
               arg:执行该可执行文件时需要传递的参数
              NULL :参数传递结束标志
       返回值:
            出错:-1
     

 int execlp(const char *file, const char *arg, …   /* (char  *) NULL */);
       功能:从PATH指定的系统路径下寻找该可执行文件
       参数:
                file:需要执行的可执行文件的名称(系统路径下已有的文件)
               arg : 执行该可执行文件时需要传递的参数

       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[]);

l:list  列表
p:path  路径 : 系统路径
v:vector 容器
e:env  环境变量

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

int main(int argc, char const *argv[])
{
//execl("/usr/bin/pstree", "pstree", "-p", NULL);

char *arg[] = {"ls", "-l", NULL};
//execv("/bin/ls", arg);

//execlp("ls", "ls", "-l", NULL);

execvp("ls", arg);
return 0;
}

3.system函数

system 通过 fork-exec 启动 shell 来执行命令(支持管道/重定向等 shell 特性),并自动处理进程等待和信号,返回命令的退出状态;而 exec 直接替换当前进程为指定程序(不启动 shell,无返回),需配合 fork 使用并手动管理子进程。

与exec函数族关键区别:

shell 处理:system 调用 /bin/sh 解析命令,exec 直接执行程序。

进程控制:system 阻塞等待命令完成,exec 替换当前进程(若成功则不返回)。

返回值:system 返回命令状态,exec 仅在失败时返回(成功则执行新程序)。

使用场景:system 适合简单命令调用,exec 适合精确控制进程替换。

用execl函数实现system函数

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

int main(int argc, char const *argv[])
{
pid_t pid = fork();

if(pid > 0)
{
printf("pid = %d",getpid());

}
else if(0 == pid)
{
printf("pid = %d\\n", getpid());
execl("/bin/ls", "ls", "-l", NULL);
}
else
{
perror("fork error");
exit(0);
}

pid_t pidtmp = wait(NULL);
printf("pidtmp = %d\\n", pidtmp);
return 0;
}

4.线程的基本概念

1. 什么是线程
     轻量级的进程,可实现多任务的并发。
     进程是操作系统资源分配的最小单位;
     线程是操作系统任务调度的最小单位。    
2. 线程的创建
     线程由某个进程创建。
     进程创建线程时,会为其分配独立的(8M)栈区空间;
     线程和所在进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。

3. 线程的调度
     宏观并行,微观串行     

4. 线程消亡
      1.  线程退出
      2. 回收线程资源空间

5.进程与线程的区别

进程:

           进程是操作系统资源分配的最小单位;
     资源消耗:进程资源开销大,每次创建都需要有0-4G的虚拟内存空间   
     效率角度:由操作系统创建,创建时耗时比线程大;跨进程调度比跨线程调度慢;
     通信方面: 进程间不能直接通信,需要使用进程间通信机制(IPC机制)
     安全性角度:进程安全性比线程高,各进程空间独立

     

线程:

              线程是操作系统任务调度的最小单位。
     资源消耗:资源开销较小,只需要所在进程为其开辟8M的栈区空间
     效率角度:由所在进程创建;跨进程调度比跨线程调度慢;
     通信方面:通信简单,可以使用线程共享的区域进行通信(比如全局变量)
     安全性角度:线程没有进程安全性好,一个线程异常可能影响同一进程中的所有线程
 

6.线程的相关编程

(1)线程的创建

头文件:

            #include <pthread.h>

函数接口:

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
      功能:创建一个新的线程
      参数:
              thread : 保存线程ID的变量地址
              attr:线程属性的对象地址
                       NULL : 按照默认属性创建
             start_routine:函数的指针:指向线程启动后要执行的任务(线程任务函数)
             arg:为线程任务函数传递的参数
     返回值:
            成功:0
            失败:非0

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

void *tash(void *arg)
{
printf("tid = %ld\\n", pthread_self());
}

int main(int argc, char const *argv[])
{
pthread_t tid;

int ret = pthread_create(&tid, NULL, tash, NULL);
if(ret != 0)
{
printf("pthread create error\\n");
return -1;
}

sleep(2);

return 0;
}

赞(0)
未经允许不得转载:网硕互联帮助中心 » Linux软件编程-进程(2)及线程(1)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!