进程替换 ——exec族函数、线程

exec函数族 

#include <unistd.h>` //exec函数族的头文件
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
  1. 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回;
  2. 如果调用出错则返回-1;
  3. 所以exec函数只有出错的返回值而没有成功的返回值

  4. //结尾必须是NULL

功能:
        利用进程空间执行另外一份代码,使得进程能够在运行时动态地加载和执行不同的程序.
    
    l:参数以列表形式传递
    v:参数以指针数组形式传递
    e:更新环境变量
    p:在系统指定目录下查找文件

1.int execl(const char *path, const char *arg, ...
                    /* (char  *) NULL */);

#include "head.h"int main(void)
{execlp("ls", "ls", "-l", NULL);return 0;
}
#include "head.h"int main(void)
{char *parg[5] = {"./hello", "how", "are", "you", NULL};printf("execl上面\n");
//	execl("./hello", "./hello", "how", "are", "you", NULL); //列表形式execv("./hello", parg);//指针形式perror("看到我,execl就失败了!\n");return 0;
}
#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);//ls -l a.txtparg[cnt] = strtok(commandbuf, " ");cnt++;while ((parg[cnt] = strtok(NULL, " ")) != NULL){cnt++;}pid = fork();if(-1 == pid){perror("fail to fork");return -1;}if (0 == pid){execvp(parg[0], parg);}wait(NULL);return 0;
}int main(void)
{printf("system上面!\n");MySystem("ls -l");printf("system下面!\n");return 0;
}

 

getenv
    char *getenv(const char *name);
    功能:
        获得环境变量名对应的值
    
    setenv
    int setenv(const char *name, const char *value, int overwrite);
    功能:
        设置环境变量的值

#include "head.h"extern char **environ; //声明了一个外部全局变量 environ,用于访问当前进程的环境变量数组。int main(void)
{int i = 0;char tmpbuff[1024] = {0};printf("================================================\n");for (i = 0; environ[i] != NULL; i++){printf("environ[%d] = %s\n", i, environ[i]);}printf("================================================\n");printf("PATH:%s\n", getenv("PATH"));//获取并输出环境变量 PATH 的值。printf("================================================\n");getcwd(tmpbuff, sizeof(tmpbuff));//getcwd 获取当前工作目录的绝对路径setenv("PATH", tmpbuff, 1);//setenv 将路径设置为新的 PATH 环境变量的值。printf("================================================\n");printf("PATH:%s\n", getenv("PATH"));printf("================================================\n");printf("上面!\n");execlp("hello", "hello", "how", "are", "you", NULL);perror("fail to execlp");printf("下面!\n");return 0;
}

线程

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

    2.线程创建:
        线程独占栈空间,文本段、数据段和堆区与进程共享
    
    3.线程调度:
        与进程调度是一样的
        宏观并行,微观串行
    
    4.线程消亡:
        与进程消亡是一样的

    5.进程和线程的区别:
        进程是操作系统资源分配的最小单元
        线程是CPU任务调度的最小单元

    6.多进程和多线程的优缺点:
        效率:多线程 > 多进程 
             多线程只需在同一进程空间内切换
             多进程需要在不同的空间中切换
        
        通信:多线程 > 有进程
            线程共享全局变量,可以通过全局变量实现数据通信
            进程空间是独立的,没有共享空间,通信实现比较复杂

        通信实现:多进程 > 多线程
            线程共享空间操作时会引发资源竞争
            进程没有共享空间,不存在资源竞争的问题
        
        安全:多进程 > 多线程
            一个进程异常不会影响其余进程空间
            一个线程异常结束会导致进程异常结束,进程异常结束,该进程内所有线程任务均无法向下执行

7.线程相关的函数接口:
        创建: fork      pthread_create 
        退出: exit      pthread_exit 
        回收: wait      pthread_join 

        1.pthread_create
          int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
          功能:
            在该进程中创建一个新的线程
          参数:
            thread:存放线程ID空间首地址
            attr:线程属性空间首地址
            start_routine:线程要执行的函数的入口
            arg:给线程函数的参数
          返回值:
            成功返回0 
            失败返回错误码

        编译时加 -lpthread选项  

        2.pthread_self
          pthread_t pthread_self(void);
          功能:
            获得调用该函数线程的ID  

#include "head.h"void *threadfun(void *arg)
{printf("线程(%#x)开始执行!\n", (unsigned int)pthread_self());return NULL;
}int main(void)
{int ret = 0;pthread_t tid;ret = pthread_create(&tid, NULL, threadfun, NULL);if (ret != 0){perror("fail to pthread_create");return -1;}while (1){}return 0;
}

        练习:创建三个线程任务,线程打印 线程(TID:XXXX)开始执行

#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 
          void pthread_exit(void *retval);
          功能:
            让调用该函数的线程任务结束
          参数:
            retval:线程结束的值
        
        4.pthread_join 
          int pthread_join(pthread_t thread, void **retval);
          功能:
            回收线程空间
          参数:
            thread:线程的ID号
            retval:存放线程结束状态空间的首地址
          返回值:
            成功返回0 
            失败返回错误码
 

void *thread(void *arg)
{printf("线程(TID:%#x)开始执行\n", (unsigned int)pthread_self());sleep(10);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;
}

创建4个线程任务,任务一循环间隔1s打印"采集线程正在执行" 任务二循环间隔2s打印"存储线程正在执行" 任务三循环间隔5s打印"告警线程正在执行" 任务四循环间隔10s打印"日志线程正在执行"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/494164.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows 文件授权问题

跨平台可执行权限介绍 在类 Unix 系统&#xff08;如 Mac, Linux&#xff09;中&#xff0c;执行权限是通过文件的权限位来控制的。而在 Windows 系统中&#xff0c;执行权限通常取决于文件扩展名和关联的执行程序&#xff0c;所以&#xff0c;当我们在跨平台的开发环境中&…

面试redis篇-13Redis为什么那么快

Redis是纯内存操作,执行速度非常快采用单线程,避免不必要的上下文切换可竞争条件,多线程还要考虑线程安全问题使用I/O多路复用模型,非阻塞IOI/O多路复用模型 Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度, I/O多路复用模型主要就是实现了高效…

win系统环境变量设置后不马上启用解决方法

目录 1. 刷新系统变量缓存2. 查看环境变量,检查是否真的保存成功了3. 重启系统(最后的玄学)总结 欢迎关注 『发现你走远了』 博客&#xff0c;持续更新中 欢迎关注 『发现你走远了』 博客&#xff0c;持续更新中 1. 刷新系统变量缓存 有时候系统会缓存环境变量&#xff0c;导致…

Zoho ToDo 满足您的需求:任务管理满足隐私和安全要求

任务管理工具已经成为我们日常生活中不可或缺的一部分&#xff0c;它们帮助我们处理各种事务&#xff0c;从杂项和愿望清单到管理截止日期和资源。这些工具不仅仅是简单的任务列表&#xff0c;它们掌握了项目的蓝图、雄心勃勃的目标和完成的最后期限。然而随着这些工具的使用越…

【LeetCode】【滑动窗口长度不固定】978 最长湍流子数组

1794.【软件认证】最长的指定瑕疵度的元音子串 这个例题&#xff0c;是滑动窗口中长度不定求最大的题目&#xff0c;在看题之前可以先看一下【leetcode每日一题】【滑动窗口长度不固定】案例。 题目描述 定义&#xff1a;开头和结尾都是元音字母&#xff08;aeiouAEIOU&…

Spring-Cloud-Gateway集成Sentinel限流

1&#xff09;gateway添加sentinel相关依赖 <spring-cloud.version>2021.0.1</spring-cloud.version> <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version><dependencies><!--gateway--><dependency><gro…

DALL·E 3:Improving Image Generation with Better Captions

论文链接&#xff1a;https://cdn.openai.com/papers/dall-e-3.pdf DALLE3 API&#xff1a;https://github.com/Agora-X/Dalle3 官网链接&#xff1a;添加链接描述 DALLE3讲解视频&#xff1a;B站视频 推荐DALLE2的讲解视频&#xff1a;B站&#xff1a;跟李沐学AI 之前精讲的DA…

Spring08、使用注解开发

8、使用注解开发 8.1、说明 在spring4之后&#xff0c;想要使用注解形式&#xff0c;必须得要引入aop的包 在配置文件当中&#xff0c;还得要引入一个context约束 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.sprin…

一次奇怪的事故:机器网络连接打满,导致服务不可用

业务背景 发生事故的业务系统是一个toB业务&#xff0c;业务是服务很多中小企业进行某项公共信息指标查询。系统特点:业务处理相对简单&#xff0c;但是流量大&#xff0c;且对请求响应要求较高&#xff1a; 业务请求峰值qps达50w&#xff0c;平时流量达20w左右。 请求响应时…

算法沉淀——动态规划之子数组、子串系列(上)(leetcode真题剖析)

算法沉淀——动态规划之子数组、子串系列 01.最大子数组和02.环形子数组的最大和03.乘积最大子数组04.乘积为正数的最长子数组长度 01.最大子数组和 题目链接&#xff1a;https://leetcode.cn/problems/maximum-subarray/、 给你一个整数数组 nums &#xff0c;请你找出一个具…

GDB动态调试学习-2-【断点 观察点】

文章目录 在程序地址上打断点在程序入口处打断点获取程序入口地址 在命名空间设置断点命名空间给命名空间的函数下断电 在文件行号上打断点保存已经设置的断点设置临时断点设置条件断点忽略断点 在程序地址上打断点 当调试汇编程序&#xff0c;或者没有调试信息的程序时&#…

【c语言】if 选择语句

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…