一、exec函數族
????????在一個進程里面執行另一個文件
? ? ? ? 本質:將文本區的指令代碼替換成exec要執行的指令
#include <unistd.h>
參數:path:要執行的可執行文件的路徑和名稱
arg:執行該可執行文件時需要傳遞的參數
NULL:參數傳遞結束標志
返回值:錯誤為1,正確不返回
int execlp(const char *file, const char *arg, .../* (char ?*) NULL */);
功能:從PATH指定的系統路徑下尋找該可執行文件
參數:file:需要執行的可執行文件的名稱(系統路徑下已有的文件)
?????????arg:執行該可執行文件時需要傳遞的參數
????????NULL:參數傳遞結束標志
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
execle
?函數允許自定義環境變量傳遞給新程序。參數?path
?為可執行文件的完整路徑,arg
?為參數列表,envp
?是一個字符串數組,表示新的環境變量(格式為?"KEY=value"
),以?NULL
?結尾。
int execv(const char *path, char *const argv[]);
execv
?與?execl
?功能相同,但參數傳遞方式不同。execv
?使用字符串數組?argv
?傳遞參數(數組末尾需為?NULL
),適合動態生成參數的場景。
int execvp(const char *file, char *const argv[]);
execvp
?結合了?execv
?和?execlp
?的特點:從系統路徑查找可執行文件,并通過數組傳遞參數。參數?file
?為文件名,argv
?為參數數組(含命令自身)。
int execvpe(const char *file, char *const argv[],char *const envp[]);
execvpe
?是?execvp
?的擴展版本,支持自定義環境變量。參數?envp
?為環境變量數組,格式與?execle
?相同。非標準函數,需確保系統支持(如 GNU 擴展)。
代碼
#include <stdio.h>int main(void)
{printf("Hello World!\n");return 0;
}
編譯命令為gcc text.c -o hello
#include<stdio.h>
#include<unistd.h>int main(int argc, char const *argv[])
{//execl("./hello", "./hello", NULL);//execl("/bin/ls", "ls", "-l", NULL);//execlp("ls", "ls", "-l", NULL);//char *arg[] = {"ls", "-l", NULL};//execv("/bin/ls", arg);// char *arg[] = {"ls", "-l", NULL};// execvp("ls", arg);return 0;
}
l:list ?列表
p:path ?路徑 : 系統路徑
v:vector 容器
e:env ?環境變量
二、system
system相當于調用了一次fork(),父進程等待子進程運行結束后,在進行運行
不調用system函數接口,實現system的功能
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>int my_system(char *buff)
{char *arg[10] = {NULL};int i = 0;char cmd[512] = {0};strcpy(cmd, buff);arg[i] = strtok(cmd, " ");while (arg[i] != NULL){printf("arg[%d] = %s\n", i, arg[i]);i++;arg[i] = strtok(NULL, " ");}pid_t pid = fork();if (pid > 0){wait(NULL);}else if (0 == pid){execvp(arg[0], arg);}return 0;}int main(int argc, const char *argv[])
{printf("system : pid = %d\n", getpid());
// system("./hello");my_system("ls -l");printf("After system\n");return 0;
}
三、線程
1.什么是線程
? ? ? ? 輕量級的線程,可實現多任務的并發。
進程是操作系統資源分配的最小單位;
線程是操作系統任務調度的最小單位。
2.線程的創建
????????線程由某個進程創建。
? ? ? ? 進程創建線程時,會為其分配獨立的8M的獨立的棧區空間
????????線程所在的進程,以及進程中的其他線程,共用進程的堆區、數據區、文本區。
3.線程的調度
? ? ? ? 宏觀并行,微觀串行
4.線程的消亡
? ? ? ? 1)線程退出
? ? ? ? 2)回收線程資源空間
5.進程和線程的區別
????????1)進程
????????資源消耗:
????????????????進程是操作系統資源分配的最小單位;
????????????????資源開銷大,每次創建都需要0-4G的虛擬空間
????????效率方面:
????????????????由操作系統創建,耗時比線程久;跨進程調度比跨線程慢
????????通信方面:
????????????????進程間不能之間通信,需要使用進程間通信機制(IPC)機制
????????安全性角度:
????????????????進程安全性比線程高,各進程空間獨立
????????2)線程
????????資源消耗:
????????????????線程是操作系統任務調度的最小單位。
????????????????資源開銷小,只需要所在進程為其開辟8M的棧區空間
????????效率方面:
????????????????????????由所在進程創建跨進程調度比跨線程調度慢:
????????通信方面:
????????????????????????通信簡單,可以使用線程共享的區域進行通信(比如全局變量)
????????安全性角度:
????????????????????????線程沒有進程安全,一個線程異常可能影響同一進程中所有線程
6.線程的相關編程
1)線程的創建
#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
功能:
????????創建一個新線程
參數:
????????thread:保存線程ID的變量地址
????????attr:線程屬性的對象地址
????????NULL:按照默認屬性創建
?????????void *(*start_routine) (void *):函數指針,函數名start_routine,指向線程啟動后要執行的任務(線程任務函數)
????????arg:為線程任務函數傳遞的參數
返回值:
????????成功:0
????????失敗:非0
????????pthread—self():獲取當前線程ID號
????????pthread_create是不是linux函數,編譯和鏈接時要加-lpthread
????????進程創建線程后,進程不能先退出,加sleep()
2)線程調度;由操作系統調度
3)線程退出
? ? ? ? I.線程退出
????????????????void pthread_exit(void *retval);
????????????????功能:退出一個線程任務
????????????????參數:
????????????????????????retval:向回收的線程傳遞的參數的地址(NULL表示不傳遞參數)
? ? ? ? II.線程回收
????????????????int pthread_join(pthread t thread, void * *retval).
????????????????功能:回收線程資源空間
????????????????參數:
thread:要回收的線程ID
????????????????????????retvaf用來保存線程退出時傳遞的參數(NULL表示不傳遞參數)
? ? ? ????????? 返回值:
? ? ? ? ????????????????成功:0
? ? ? ? ? ? ? ? ? ? ? ? 失敗-1
? ? ? ? ? ? ? ??III:線程屬性
? ? ? ? ? ? ? ? ? ? ? ? 1.分離屬性:不需要被其他線程回收的線程稱為分離屬性得到線程,將來會被操作系統所回收
? ? ? ? ????????int pthread_detach(pthread_t thread);
? ? ? ????????? 功能:將線程設置為分離屬性的線程
? ? ? ? ? ? ? ? ? ? ? ? 2.非分離屬性:可以被其他線程回收或者結束的線程,稱為非分離屬性的線程(默認屬性:非分離屬性)
? ? ? ? ? ? ? ? IV:線程回收策略:
? ? ? ? ? ? ? ? 1.分離屬性的線程:不需要回收。(沒有空閑的線程可以幫忙回收時)
? ? ? ? ? ? ? ? 2.非分離屬性的線程:pthread_join()阻塞回收
7.線程間通信
? ? ? ? 全局變量通信
? ? ? ? 臨界資源:多個線程可以同時訪問的資源稱為臨界資源:比如,全局變量、共享內存區域等
? ? ? ? 如何解決資源競爭問題:
? ? ? ? ? ? ? ? 1)互斥機制:多個線程訪問臨界資源時,具有排他性訪問的機制(一次只允許一個線程對該臨界資源進行訪問)
? ? ? ? ? ? ? ? 互斥鎖->解決資源競爭問題。
? ? ? ? ? ? ? ? 步驟:
? ? ? ? ? ? ? ? ? ? ? ? 1.創建互斥鎖:pthread_utex_t?
? ? ? ? ? ? ? ? ? ? ? ? 2.初始化互斥鎖:pthread_mutex_init
? ? ? ? ? ? ? ? ? ? ? ? 3.加鎖:pthread_mutex_lock
? ? ? ? ? ? ? ? ? ? ? ? 4.解鎖:pthread_mutex_unlock
? ? ? ? ? ? ? ? ? ? ? ? 5.銷毀鎖:pthread_mutex_destroy
int pthread mutex init(pthread mutex t *restrict mutex.const pthread mutexattr t*restrict attr)
????????功能:初始化互斥鎖
????????參數:mutex:鎖對象地址
attr:鎖的屬性(NULL:默認屬性)
????????返回值:成功:0
? ? ? ? ? ? ? ? ? ? ?失敗:-1
int pthread_mutex_lock(pthread_mutex_t *mutex);
????????功能:加鎖
int pthread_mutex_unlock(pthread_mutex_t *mutex);
? ? ? ? 功能:解鎖
int pthread_mutex_destroy(pthread_mutex_t *mutex);
? ? ? ? 功能:銷毀鎖
四、線程相關代碼
1.創建線程
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
void *task(void *arg)
{printf("I am thread : tid = %ld\n", pthread_self());
}int main(int argc, char const *argv[])
{pthread_t tid;int ret = pthread_create(&tid, NULL, task, NULL);if(ret != 0){printf("pthread_create error\n");return -1;}sleep(2);return 0;
}
2.讓線程輸出一個學生的信息
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>struct stu
{int id;char name[20];
}Stu;void *task(void *arg)
{struct stu *student = (struct stu *)arg; printf("%d\n%s\n", student->id, student->name);return NULL;
}int main(int argc, char const *argv[])
{pthread_t tid;struct stu s = {1,"wang"};int ret = pthread_create(&tid, NULL, task, &s);if(ret != 0){printf("pthread_create error\n");return -1;}sleep(1);return 0;
}
3.線程模擬無人機工作
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>void *task1(void *arg)
{ while(1){printf("主控模塊正在運行\n");pthread_exit(NULL);}
}void *task2(void *arg)
{ while(1){printf("控制模塊正在運行\n");pthread_exit(NULL);}
}void *task3(void *arg)
{ while(1){printf("圖像采集模塊正在運行\n");pthread_exit(NULL);}
}void *task4(void *arg)
{ while(1) {printf("圖像發送模塊正在運行\n");pthread_exit(NULL);}
}void *task5(void *arg)
{ while(1){printf("指令接收模塊正在運行\n");pthread_exit(NULL);}
}int main(int argc, char const *argv[])
{pthread_t tid1;pthread_t tid2;pthread_t tid3;pthread_t tid4;pthread_t tid5;int ret1,ret2,ret3,ret4,ret5;ret1 = pthread_create(&tid1, NULL, task1, NULL);ret2 = pthread_create(&tid2, NULL, task2, NULL);ret3 = pthread_create(&tid3, NULL, task3, NULL);ret4 = pthread_create(&tid4, NULL, task4, NULL);ret5 = pthread_create(&tid5, NULL, task5, NULL);if(0 != ret1 && 0 != ret2 && 0 != ret3 && 0 != ret4 && 0 != ret5){printf("pthread_create error\n");return -1;}sleep(1);pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);pthread_join(tid4, NULL);pthread_join(tid5, NULL);return 0;
}
4.加互斥鎖解決資源競爭問題
#include <stdio.h>
#include <pthread.h>int num_g = 0;
pthread_mutex_t mutex;void *task1(void *arg)
{for (int i = 0; i < 100000; i++){pthread_mutex_lock(&mutex);num_g = num_g+1;printf("num_g = %d\n", num_g);pthread_mutex_unlock(&mutex);}
}void *task2(void *arg)
{for (int i = 0; i < 100000; i++){pthread_mutex_lock(&mutex);num_g = num_g+1;printf("num_g = %d\n", num_g);pthread_mutex_unlock(&mutex);}}int main(int argc, const char *argv[])
{pthread_t tid[2];pthread_mutex_init(&mutex, NULL);pthread_create(&tid[0], NULL, task1, NULL);pthread_create(&tid[1], NULL, task2, NULL);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);pthread_mutex_destroy(&mutex);return 0;
}