exec函数族;线程的创建、调度、消亡;pthread_~~~函数接口、二级指针的应用

我要成为嵌入式高手之2月26日Linux高编第九天!!

学习笔记

进程

一、exec函数族

        extern char **environ;

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

功能:利用进程空间执行另外一份代码

l:参数以列表形式传递

优先在当前目录寻找

lp:参数在系统路径以列表形式传递

在系统路径(/bin)下找程序

优先在系统路径下找

1、getenv

#include <stdlib.h>

char *getenv(const char *name);

功能:获得环境变量名对应的值

2、setenv

#include <stdlib.h>

int setenv(const char *name, const char *value, int overwrite);

功能:设置环境变量的值

参数:

        name:环境变量名

        value:要赋给环境变量的值

        overwrite:权限:非0  覆盖;0 不覆盖

返回值:成功返回0;失败返回-1;

v:参数以指针数组传递

  

vp: 参数在系统路径下以指针数组形式传递

int execvp(const char *file, char *const argv[]);

#include "head.h"

int MySystem(const char *pcommand)
{
    char commandbuf[1024] = {0};
    char *parg[10] = {NULL};
    int cnt = 0;
    pid_t pid;

    strcpy(commandbuf, pcommand);

    parg[cnt] = strtok(commandbuf, " ");
    cnt ++;

    while ((parg[cnt] = strtok(NULL, " ")) != NULL)
    {
        cnt++;
    }

    pid = fork();
    if (pid == -1)
    {
        perror("fail to fork");
        return -1;
    }
    if (pid == 0)
    {
        execvp(parg[0], parg);
    }
    wait(NULL);

    return 0;
}

int main(void)
{
    printf("system up\n");
    MySystem("ls -l execvp.c");
    printf("system under\n");

    return 0;
}

e:更新环境变量

p:在系统指定目录下查找文件

线程

一、基本概念

线程:线程是一个轻量级的进程,位于进程空间内部,一个进程中可以创建多个线程

二、线程的创建

线程独占栈空间;文本段、数据段和堆区和进程共享

三、线程调度

与进程调度保持一致

宏观并行,微观串行

四、线程消亡

与进程消亡是一样的

五、进程和线程的区别

进程是操作系统资源分配的最小单元

线程是CPU任务调度的最小单元

六、多进程和多线程的优缺点

效率:多线程>多进程,因为线程位于进程空间内部,多线程只需在同一 进程空间内进行切换,多进程则需要在不同空间中进行切换。

通信:多线程>多进程,线程共享全局变量,可以通过全局变量实现数据通信;进程空间是独立的,没有共享空间,通信实现比较复杂。

通信实现:多进程>多线程,线程共享空间操作时会引发资源竞争;进程没有共享空间,不存在资源竞争的问题

安全性: 多进程>多线程,一个进程异常不会影响其余进程空间;一个线程异常结束会导致进程异常结束,进程若异常结束,该进程内所有线程任务均无法向下执行

七、线程相关的函数接口

创建:fork        pthread_create

退出:exit        pthread_

回收:wait

1、pthread_create

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

功能:在该进程中创建一个新的线程

参数:

        thread:存放线程ID的空间首地址

        attr:线程属性的空间首地址

        start_routine:线程要执行的函数的入口

                void *(*start_routine) (void *)

                

        arg:给线程函数的参数

返回值:成功返回0;失败返回错误码

编译时加 -lpthread

2、pthread_self

#include <pthread.h>

pthread_t pthread_self(void);

功能:获得调用该函数线程的TID

练习:创建三个

/*多个线程执行相同任务*/
#include "head.h"

void *threadfun(void *arg)
{
    printf("线程(%#x)开始执行!\n", (unsigned int)pthread_self());
    
    return NULL;
}

int main(void)
{
    int ret = 0;
    int i = 0;
    pthread_t tid[3];
    for (i = 0; i < 3; ++i)
    {
        ret = pthread_create(&tid[i], NULL, threadfun, NULL);
        if (ret != 0)
        {
            perror("fail to pthread_create");
            return -1;
        }
    }
    while (1)
    {

    }

    return 0;
}

/*不同线程执行不同功能*/
#include "head.h"

void *thread1(void *arg)
{
    printf("线程1(TID:%#x)开始执行\n", (unsigned int)pthread_self());

    return NULL;
}

void *thread2(void *arg)
{
    printf("线程2(TID:%#x)开始执行\n", (unsigned int)pthread_self());

    return NULL;
}

void *thread3(void *arg)
{
    printf("线程3(TID:%#x)开始执行\n", (unsigned int)pthread_self());

    return NULL;
}

int main(void)
{
    pthread_t tid[3];
    void *(*p[3])(void *) = {thread1, thread2, thread3};
    int i = 0;

    for (i = 0; i < 3; ++i)
    {
        pthread_create(&tid[i], NULL, p[i], NULL);
    }

    while (1)
    {

    }

    return 0;
}

 3、pthread_exit

#include <pthread.h>

void pthread_exit(void *retval);

功能:让调用该函数的线程任务结束

参数:retval 线程结束的值

4、pthread_join

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

功能:回收线程空间

参数:

        thread:线程的TID号

        retval:存放线程结束状态空间的首地址

返回值:成功返回0,失败返回错误码

5、pthread_cancel

#include <pthread.h>

int pthread_cancel(pthread_t thread);

功能:杀死线程

参数:thread 线程的TID号

返回值:成功返回0;失败返回错误码

二级指针的应用场景:

1、指针数组传参时传递二级指针

        char *argv[10];

2、函数体内部修改函数体外部指针变量值的时候传递指针变量的地址(即二级指针)

        char *pNum = NULL;

        Fun(&pNum);

#include "head.h"

void *thread(void *arg)
{
    printf("线程(TID:%#x)开始执行\n", (unsigned int)pthread_self());
    sleep(5);
    printf("线程即将结束\n");
    pthread_exit("Game Over!");

    return NULL;
}

int main(void)
{
    pthread_t tid;
    void *arg = NULL;

    pthread_create(&tid, NULL, thread, NULL);

    pthread_join(tid, &arg);//取指针的地址,为二级指针
    /*函数体内部修改函数体外部指针变量的时候传递指针变量的地址*/
    printf("arg = %s\n", (char *)arg);

    return 0;
}

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值