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:参数以列表形式传递
v:参数以指针数组形式传递
e:更新环境变量
p:在系统指定目录下查找文件
1)自定义一个程序(文件名为apple)
#include "head.h"int main(int argc,const char *argv[])
{int i = 0;printf("=============================\n");printf("how are you!\n");for (i = 0; i < argc; ++i){printf("argv[%d] = %s\n",i,argv[i]);}return 0;
}
2)int execl/int execv引用运行
#include "head.h"int main(void)
{
// char *argv[5] = {"./hello","apple","bullll",NULL};printf("1111111\n");execl("./apple","./hello","apple","bullll",NULL); //以参数形式传递 第一个时要运行的文件路径 后面是传递的参数
// execv("./apple",argv); //以指针数组形式传递 定义指针数组如上printf("222222222222222\n");return 0;
}
getenv
char *getenv(const char *name);
功能:获得环境变量名对应的值
setenv
int setenv(const char *name, const char *value, int overwrite);
功能:设置环境变量的值
参数:
name:环境变量名
value:环境变量的值
overwrite:非0 覆盖
0 不覆盖
返回值:成功返回0;失败返回-1
#include "head.h"int main(void)
{char tmpbuff[1024] = {0};printf("================================\n");printf("PATH:%s\n",getenv("PATH")); //获得PATH的系统路径printf("================================\n");getcwd(tmpbuff,sizeof(tmpbuff)); //得到将当前路径 并将其放到数组中setenv("PATH",tmpbuff,1); //将PATH的路径替换为数组中的内容printf("=================================\n");printf("PATH:%s\n",getenv("PATH")); //打印替换后的路径printf("=================================\n");execlp("apple","./hell","apple","bullll",NULL); //参数以列表形式 在系统路径下查找文件 并执行 注:第一个参数是要执行的文件名return 0;}
system
int system(const char *command);
功能:执行shell命令
特点:传递一个命令参数,执行成功后,会回到原来程序运行的位置继续向下执行,而exec函数是执行失败后回到原来的位置继续向下执行;者两点注意区分。
#include "head.h"int Msystem(const char *p)
{char tmpbuff[1024] = {0};char *parg[10] = {0};int cout = 0;strcpy(tmpbuff,p); //将传过来的字符串常量以字符串的形式给到数组中parg[cout] = strtok(tmpbuff," "); //在第一个空格的地方分解字符串cout++;while ((parg[cout] = strtok(NULL," ")) != NULL) //将剩余的字符串继续以空格分割 放到指针数组中{cout++;}pid_t pid; pid = fork(); //创建一个子进程用来单独执行命令if (pid == -1){perror("fail to fork");return -1;}if (pid == 0) {execvp(parg[0],parg); //调用execvp函数 参数以指针数组的形式 在系统目录下找到该命令并执行}wait(NULL); //当子进程结束 回收子进程return 0;
}int main(void)
{printf("system上面!\n");Msystem("ls -l"); //封装一个system函数printf("system下面!\n");return 0;
}
线程
1.基本概念
线程:是一个轻量级的进程,位于进程空间内部,一个进程可以创建多个线程
2.线程的创建
线程独占栈空间,文本段,数据段,和堆区与进程共享
3.线程的调度
与进程调度一样的:宏观并行,微观串行
4.线程的消亡
僵尸态:线程代码结束,空间没有被回收,称为僵尸线程
5.进程和线程的区别
1)进程是操作系统资源分配的最小的单元;
2)线程是CPU任务调度的最小单元(多线程的系统和调度比进程更节省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选项
练习:
创建三个线程,并执行
/****************************************一次创建多个不同的线程*每个线程执行不同的任务*可以定义一个函数指针数组进行遍历* ************************************/
#include "head.h"void *threadfun1(void *argc)
{printf("线程1(%#x)开始!\n",(unsigned int)pthread_self());return 0;
}void *threadfun2(void *argc)
{printf("线程2(%#x)开始!\n",(unsigned int)pthread_self());return 0;
}void *threadfun3(void *argc)
{printf("线程3(%#X)开始!\n",(unsigned int)pthread_self());return 0;
}int main(void)
{int ret = 0;int i = 0;pthread_t tid[3];void* (*tip[3])(void*) = {threadfun1,threadfun2,threadfun3}; //有一个void*返回值并有一个void*参数的函数指针数组for (i = 0; i < 3; ++i){ret = pthread_create(&tid[i],NULL,tip[i],NULL);if (ret != 0){perror("fail to pthread");return -1;}}while(1){}return 0;
}
2. pthread_self
pthread_t pthread_self(void);
功能:
获得调用该函数线程的ID
3.pthread_exit
void pthread_exit(void *retval);
功能:
让调用该函数的线程任务结束
参数:
retval:线程结束的值
4.pthread_join
int pthread_join(pthread_t thread, void **retval);
功能:
回收线程空间
参数:
thread:线程的ID号
retval:存放线程结束状态空间的首地址
返回值:
成功返回0
失败返回错误码
示例:
#include "head.h"void *thread(void* argc)
{printf("进程开始!(PID:%#x)\n",(unsigned int)pthread_self());printf("进程即将结束!\n");sleep(5);printf("结束!\n");pthread_exit("over!");return NULL;
}int main(void)
{int ret = 0;pthread_t tid;void *gid = NULL;ret = pthread_create(&tid,NULL,thread,NULL);if (ret != 0){perror("fail to pthread");return -1;}pthread_join(tid,&gid);printf("gid=%s\n",(char *)gid);return 0;
}