我要成为嵌入式高手之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;
}