wordpress手機QQ登錄優(yōu)化大師官方下載
嵌入式學習-IO進程-Day04
進程的函數(shù)接口
fork和Vfork
回收進程資源
wait
waitpid
退出進程
獲取進程號(getpid,getppid)
守護進程
守護進程的特點
創(chuàng)建步驟
exec函數(shù)族
線程
概念
線程和進程的區(qū)別
線程資源
線程函數(shù)接口
創(chuàng)建線程(pthread_create)
退出線程
進程的函數(shù)接口
fork和Vfork
1.fork(): 子進程拷貝父進程的數(shù)據(jù)段,代碼段
vfork(): 子進程與父進程共享數(shù)據(jù)段
2.fork(): 父子進程執(zhí)行次序不確定
vfork(): 保證子進程先運行,在調用exec()或exit()之前,與父進程數(shù)據(jù)共享,在exec()或exit()調用之后,父進程才能運行
總結:fork: 更通用,適用于需要創(chuàng)建一個完全獨立的子進程的場景,vfork: 更適用于子進程立即執(zhí)行 exec() 覆蓋其自身的場景,因為它避免了不必要的地址空間復制,提高了性能。
回收進程資源
wait
#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *wstatus);
功能:回收子進程資源(阻塞)
參數(shù):status:子進程退出狀態(tài),不接受子進程狀態(tài)設為NULL
返回值:成功:回收的子進程的進程號
失敗:-1
用法:wait(NULL);
示例代碼:
waitpid
pid_t waitpid(pid_t pid, int *status, int options);
功能:回收子進程資源
參數(shù):
pid:>0 指定子進程進程號=-1 任意子進程=0 等待其組ID等于調用進程的組ID的任一子進程<-1 等待其組ID等于pid的絕對值的任一子進程
status:子進程退出狀態(tài)
options:0:阻塞
WNOHANG:非阻塞
返回值:正常:結束的子進程的進程號
當使用選項WNOHANG且沒有子進程結束時:0
出錯:-1wait(NULL) == waitpid(-1,NULL,0) //阻塞回收任意子進程資源
waitpid(pid,NULL,0); //阻塞回收指定進程
waitpid(-1,NULL,WNOHANG);不阻塞回收任意子進程
非阻塞示例代碼
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{pid_t pid = fork();if (pid < 0){perror("fork err");return -1;}else if (pid == 0){printf("in child\n");sleep(5); // 睡眠是為了看到現(xiàn)象printf("子進程退出\n");}else{printf("嘗試回收我的子進程資源\n");while (1){pid_t result = waitpid(pid, NULL, WNOHANG);if (result == 0){printf("子進程還在運行.....\n");sleep(1);}else{printf("子進程結束\n");break;}}}return 0;
}
退出進程
void exit(int status);
功能:結束進程,刷新緩存
參數(shù):退出的狀態(tài)
不返回。
void _exit(int status);
功能:結束進程,不刷新緩存
參數(shù):status是一個整型的參數(shù),可以利用這個參數(shù)傳遞進程結束時的狀態(tài)。
通常0表示正常結束;
其他的數(shù)值表示出現(xiàn)了錯誤,進程非正常結束exit和return的區(qū)別
exit:函數(shù),結束進程。
return:關鍵字,結束函數(shù)。exit和_exit的區(qū)別
exit():刷新緩存區(qū),關閉所有打開的文件指針
_exit():立即終止進程,不會執(zhí)行上述操作
示例代碼:
獲取進程號(getpid,getppid)
pid_t getpid(void);
功能:獲取當前進程的進程號
pid_t getppid(void);
功能:獲取當前進程的父進程號
練習:創(chuàng)建子進程,在父子進程中分別獲取他們的進程號和父進程號,獲取結束,回收子進程資源,退出進程。
守護進程
守護進程的特點
守護進程是后臺進程;生命周期比較長,從系統(tǒng)啟動時開啟,系統(tǒng)關閉時結束;它是脫離控制終端且周期執(zhí)行的進程。
創(chuàng)建步驟
1.創(chuàng)建子進程,父進程退出
子進程成為孤兒進程,成為后臺進程(fork)
2.在子進程當中創(chuàng)建會話
讓子進程成為會話組組長,為了讓子進程完全脫離終端;setsid()
3.改變進程的運行路徑為根目錄
原因進程運行的路徑不能被刪除或卸載;chdir("/")
4.重設文件權限掩碼
增大進程創(chuàng)建文件時權限,提高靈活性;umask(0)
5.關閉文件描述符
將不需要的文件關閉;close();
示例代碼:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
pid_t pid = fork();
if (pid < 0)
{
perror("fork err");
return -1;
}
else if (pid == 0)
{
//在子進程中創(chuàng)建新的會話
setsid();
//改變路徑到根目錄
chdir("/");
//改變文件權限掩碼
umask(0);
//關閉文件描述符
for (int i = 0; i < 3; i++)
{
close(i);
}
while(1);
}
else
{
exit(0);
}
return 0;
}
練習:
創(chuàng)建一個守護進程,循環(huán)間隔1s向文件中寫入一串字符“hello”
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char const *argv[])
{
pid_t pid = fork();
if (pid < 0)
{
perror("fork err");
return -1;
}
else if (pid == 0)
{
// 在子進程中創(chuàng)建新的會話
setsid();
// 改變路徑到根目錄
chdir("/");
// 改變文件權限掩碼
umask(0);
// 關閉文件描述符
for (int i = 0; i < 3; i++)
{
close(i);
}
// 打開一個文件
int fd = open("/tmp/info.log", O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd < 0)
{
perror("open err\n");
return -1;
}
// 循環(huán)寫入
while (1)
{
write(fd, "hello\n", 6);
sleep(1);
}
}
else
{
exit(0);
}
return 0;
}
exec函數(shù)族
作用:在當前進程中執(zhí)行一個新的程序。
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[]);
線程
概念
線程是一個輕量級的進程,為了提高系統(tǒng)的性能引入線程,線程和進程都參與統(tǒng)一的調度。
線程和進程的區(qū)別
共同點:都為操作系統(tǒng)提供了并發(fā)能力
不同點:
- 調度和資源上:線程是系統(tǒng)調度的最小單位,進程是資源分配的最小單位。
- 地址空間上:同一個進程創(chuàng)建多個線程共享進程資源,進程的地址空間相互獨立。
- 通信方面:線程的通信相對簡單,只需要通過全局變量就能實現(xiàn)。但是需要考慮臨界資源(臨界資源包括同一個文件,全局變量等)訪問的問題,進程間的通信相對復雜,需要借助進程間的通信機制(借助3g-4g的的內核空間)
- 安全性方面:線程的安全性相對較差,當進程結束時會導致所有線程退出,進程相對于安全。
線程資源
共享的資源:可執(zhí)行的指令,靜態(tài)的數(shù)據(jù),進程中打開的文件描述符,信號處理函數(shù)。當前的工作目錄,用戶的ID,用戶的組ID
私有資源:線程ID (TID)、PC(程序計數(shù)器)和相關寄存器、堆棧、錯誤號 (errno)、信號掩碼和優(yōu)先級、執(zhí)行狀態(tài)和屬性
線程標識:
主線程的 TID 和 PID 是相同的,每個子線程有自己獨立的 TID,但它們都共享相同的 PID
線程函數(shù)接口
創(chuàng)建線程(pthread_create)
頭文件
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
功能:創(chuàng)建一個線程
參數(shù):1.pthread_t *thread:線程標識,成功創(chuàng)建線程后,pthread_create 會將新線程的 ID 寫入 thread 指向的內存位置。2.const pthread_attr_t *attr:線程屬性, NULL:代表設置默認屬性3. void *(*start_routine):函數(shù)名,代表線程函數(shù),指向一個函數(shù)的指針,這個函數(shù)就是線程的執(zhí)行體(也就是線程的入口函數(shù))。該函數(shù)必須符合 void *(*start_routine)(void *) 的原型,即接受一個 void * 類型的參數(shù),并返回一個 void * 類型的值。 函數(shù)指針一般都是作為函數(shù)的參數(shù)使用:意思是在一個函數(shù)中回調另一方功能函數(shù)4.void *arg:傳遞給 start_routine 的參數(shù)。arg 是一個通用的指針,可以傳遞任何類型的數(shù)據(jù)(通常是一個結構體的指針,以便傳遞多個參數(shù))。如果不需要傳遞參數(shù),可以傳遞 NULL。
返回值:成功返回0
失敗返回錯誤碼
示例代碼
退出線程
void pthread_exit(void *retval);功能:用于執(zhí)行退出線程
參數(shù):任意類型的數(shù)據(jù),一般寫NULL
返回值:無
用法:
pthread_exit(NULL);