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;
- 所以exec函数只有出错的返回值而没有成功的返回值
//结尾必须是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打印"日志线程正在执行"