1.waitpid
pid_t waitpid(pid_t pid, int *wstatus, int options); 功能: 回收指定的子进程空间 参数: pid:要回收的子进程的pid wstatus:回收状态的指针 options:回收选项 0 阻塞回收 WNOHANG:非阻塞回收 返回值: 成功:返回回收的子进程的pid 失败:返回-1 |
#include "../head.h"
int main(void){
pid_t pid1;
pid_t pid2;
pid_t ret;
int status = 0;
pid1 = fork();
if(-1 == pid1){
perror("fail to fork");
return -1;
}
if(0 == pid1){
printf("子进程1(PID:%d)开始执行\n", getpid());
sleep(10);
printf("子进程1即将结束\n");
exit(0);
}else if(pid1 > 0){
pid2 = fork();
if(-1 == pid2){
perror("fail to fork");
return -1;
}
if(0 == pid2){
printf("子进程2(PID:%d)开始执行\n", getpid());
sleep(10);
printf("子进程2即将结束\n");
exit(0);
}else if(pid2 > 0){
while(1){
ret = waitpid(pid2,&status,WNOHANG);
if(-1 == ret){
perror("fail to waitpid");
return -1;
}
if(0 == ret){
printf("还有子进程没结束,先干点别的事吧!\n");
}
if(ret > 0){
break;
}
sleep(1);
}
printf("子进程2(PID:%d)已经被回收了!",ret);
if(WIFEXITED(status)){
printf("子进程被正常回收,状态值:%d\n",WEXITSTATUS(status));
}
if(WIFSIGNALED(status)){
printf("子进程被%d号信号杀死\n",WTERMSIG(status));
}
}
}
return 0;
}
2.exec函数族
extern char **environ; l:参数以列表形式传递 |
int execl(const char *path, const char *arg, .../* (char *) NULL */);
参数的结尾必须以NULL作为参数的结束标志,第一个参数传递的是要执行文件的路径
execl("./hello","./hello","how","are","you",NULL);
int execv(const char *path, char *const argv[]);
与execl不同的是execv,第二个参数用指针数组表示
char *parg[10] = {"./hello","how","are","you",NULL};
execv("./hello",parg);
int execvp(const char *file, char *const argv[]);
第一个参数可以只传要执行的代码的文件名,不用传路径,它会在一个叫系统路径PATH下寻找hello,所以要把hello放在系统目录下
getenv int setenv(const char *name, const char *value, int overwrite); |
#include "../head.h"
extern char **environ;
int main(void){
printf("exec上面,PID:%d\n",getpid());
char *parg[10] = {"./hello","how","are","you",NULL};
int i = 0;
char pathvalue[4096] = {0};
char tmpbuff[4096] = {0};
for(i = 0; environ[i] != NULL; i++){
printf("environ[%d] = %s\n",i,environ[i]);
}
printf("=======================================\n");
printf("PATH:%s\n",getenv("PATH"));
printf("=======================================\n");
getcwd(tmpbuff,sizeof(tmpbuff));
sprintf(pathvalue,"%s:%s",getenv("PATH"),tmpbuff);
setenv("PATH",pathvalue,1);//第三个参数传0会将原来的覆盖掉,如果不想覆盖传非0值
printf("=======================================\n");
printf("PATH:%s\n",getenv("PATH"));
printf("=======================================\n");
execvp("./hello",parg);
printf("exec下面\n");
}
exec和fork()搭配使用可以实现
3.system函数原型:
int system(const char *command); 功能: 在代码中执行一条shell命令 |
#include "../head.h"
int Mysystem(char const*pcommend){
char tmpbuff[4096] = {0};
int cnt = 0;
char *parg[10] = {NULL};
pid_t pid;
strcpy(tmpbuff,pcommend);
parg[cnt] = strtok(tmpbuff," ");
if(parg[cnt] == NULL){
return-1;
}
cnt++;
while(1){
parg[cnt] = strtok(NULL," ");
if(parg[cnt] == NULL){
break;
}
cnt++;
}
pid = fork();
if(-1 == pid){
return -1;
}
if(0 == pid){
execvp(parg[0],parg);
}
if(pid > 0){
wait(NULL);
}
return 0;
}
int main(void){
printf("system上面\n");
// Mysystem("ls -l");
system("ls -l");
printf("system下面\n");
return 0;
}
线程相关的函数接口:
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:线程属性 (默认属性 NULL) start_routine:线程任务函数 arg:对线程函数的传参 返回值: 成功返回0 失败返回错误码 |
注意:编译时要使用gcc filename.c -lpthread
2.pthread_self
pthread_t pthread_self(void); 功能: 获得当前线程的ID号 参数: 缺省 返回值: 成功返回线程的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 失败返回错误码 |
注意:
pthread_join具有阻塞功能,线程不结束,会阻塞等到直到线程结束回收线程空间
pthread_join具有同步功能
#include "../head.h"
void *threadfun(void * arg){
printf("线程(ID:%#lx)开始创建啦!\n",(unsigned long)pthread_self());
sleep(2);
pthread_exit("我要结束了\n");
}
int main(void){
pthread_t tid;
int ret = 0;
void *ptm = NULL;
pthread_create(&tid,NULL,threadfun,NULL);
if(-1 == ret){
fprintf(stderr,"pthread_creat failed,error = %d\n",ret);
}
printf("创建的线程ID为:%#lx\n",(unsigned long)tid);
pthread_join(tid,&ptm);
printf("线程以被回收,结束状态码:%s\n",(char *)ptm);
while(1){
}
return 0;
}