網(wǎng)站首頁 編程語言 正文
1.多進程相關概念
1.1什么是進程
進程:程序的一次執(zhí)行過程就會產(chǎn)生一個進程。進程是分配資源的最小單位(0-3G)。
進程就是一個正在執(zhí)行的任務。進程是一個動態(tài)的過程,它有生命周期隨著程序的運行
開始,隨著程序結束而消亡。每個進程都有自己的獨立的運行的空間,比如每個進程都有
自己的文件描述符,每個進程都擁有自己的緩沖區(qū)。只要用戶執(zhí)行了一個程序,在內核空間
就會創(chuàng)建一個task_struct的結構體,這個結構體就代表當前的進程。進程運行產(chǎn)生的所有
的信息都被放到這個結構體中保存著。
1.2進程和程序有什么區(qū)別
程序:程序是經(jīng)過編譯器編譯生成的二進制文件,程序在硬盤上存儲。程序是靜態(tài)的,沒有生命
? 周期的概念程序本身不會分配內存。
進程:程序的一次執(zhí)行過程就會創(chuàng)建一個進程,進程是動態(tài)的,有生命周期。進程運行的時候會
? 分配0-3G的內存空間。進程在內存上存儲。
1.3進程的組成
進程是由三個部分組成的:進程的PCB(task_struct),(程序段)文本段,數(shù)據(jù)段。
1.4進程的種類
交互進程:這種進程維護以一個終端,通過這個終端用戶可以和進程進程交互。
? 例如:文本編輯器
批處理進程:這種進程優(yōu)先級比較低,運行的時候會被放到一個運行的隊列中。
? 隨著隊列的執(zhí)行,而逐漸執(zhí)行。
? 例如gcc編譯程序的時候這個進程就是批處理進程。
守護進程:守護進程就是后臺運行的服務,隨著系統(tǒng)的啟動而啟動,隨著系統(tǒng)的終止而終止。
? 例如:windows上的各種服務
1.5什么是進程的PID
PID就是操作系統(tǒng)給進程分配的編號,它是識別進程的唯一的標識。
在linux系統(tǒng)中PID是一個大于等于0的值。
1.6特殊PID的進程
0:idle:在linux系統(tǒng)啟動的時候運行的第一個進程就是0號進程。
? 如果沒有其他的進程執(zhí)行就運行這個idle進程。
1:init:1號進程是由0號進程調用內核kernel_thread函數(shù)產(chǎn)生的第一個進程,
? 它會初始化所有的系統(tǒng)的硬件。當初始化完之后會一直執(zhí)行,比如會為
? 孤兒進程回收資源。
2:kthreadd:調度器進程,主要負責進程的調度工作。
1.7進程的狀態(tài)
1.進程運行的狀態(tài)
D// 不可中斷的休眠態(tài)(信號)
R//運行態(tài)
S//可中斷的休眠態(tài)(信號)
T//停止狀態(tài)
X//死亡狀態(tài)
Z//僵尸態(tài)(進程結束后沒有被父進程回收資源)
2.進程的附加狀態(tài)
<//高優(yōu)先級
N//低優(yōu)先級的進程
L//在內存區(qū)鎖定
s//會話組組長
l//進中包含多線程
+//前臺進程
二.進程實例
2.1進程的拷貝
#include <head.h>
int main(int argc,const char * argv[])
{
for(int i=0;i<2;i++){
fork();
printf("-");
}
return 0;
}
原理圖:
分析:上述的程序會打印8個-,上述程序一共是4個進程,因為在進程創(chuàng)建的時候會拷貝父進程的
緩沖區(qū),由于2214和2215的緩沖區(qū)沒有刷新,所以2216和2217緩沖區(qū)中有兩個-。
2.2進程創(chuàng)建的實例
#include <head.h>
int main(int argc,const char * argv[])
{
pid_t pid;
pid = fork();
if(pid == -1){
PRINT_ERR("fork error");
}else if(pid == 0){
//子進程
printf("這個就是子進程\n");
}else{
//父進程
printf("這個就是父進程\n");
}
return 0;
}
分析圖:
2.3執(zhí)行沒有先后循序
#include <head.h>
int main(int argc, const char* argv[])
{
pid_t pid;
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
//子進程
while (1) {
sleep(1);
printf("這個就是子進程\n");
}
} else {
//父進程
while (1) {
sleep(1);
printf("這個就是父進程\n");
}
}
return 0;
}
結果圖:
2.4進程創(chuàng)建的實例(父子進程內存空間問題)
父進程fork產(chǎn)生子進程的時候利用了寫時拷貝的原則
2.5使用多進程創(chuàng)建三個進程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
pid_t pid;
if((pid = fork()) ==-1){
printf("創(chuàng)建進程失敗\n");
exit(-1);
}else if(pid == 0){
pid_t tid;
if((tid = fork())==-1){
printf("%d,%d\n",getpid(),getppid());
}else if(pid == 0){
printf("%d,%d\n",getpid(),getppid());
}else{
printf("%d\n",getpid());
}
}
while(1);
return 0;
}
2.6使用多進程進行拷貝文件
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
char destfile[32]={0};
int get_length(char const *arcfile)
{
int fd,cd,length;
if((fd=open(arcfile,O_RDONLY))==-1){
printf("open file error");
exit(-1);
}
snprintf(destfile,sizeof(destfile),"new_%s",arcfile);
if((cd==open(destfile,O_WRONLY|O_TRUNC|O_CREAT,0666)==-1)){
}
length = lseek(fd,0,SEEK_END);
return length;
}
int copy_file(const char* srcfile,const char* destfile,int start,int length)
{
int sfd,dfd,ret,count = 0;
char buff[128] = {0};
int counts=0;
if((sfd=open(srcfile,O_RDONLY))==-1){
printf("open error");
}
if((dfd=open(destfile,O_WRONLY))==-1){
printf("open file error");
}
lseek(sfd,start,SEEK_SET);
lseek(dfd,start,SEEK_SET);
while (1){
ret = read(sfd,buff,sizeof(buff));
if(ret == 0){
break;
}
count+=ret;
if(count >= length){
write(dfd,buff,length-(count-ret));
break;
}
write(dfd,buff,ret);
}
return 0;
}
int main(int argc, char const *argv[])
{
pid_t pid;
if(argc!=2){
printf("輸入格式錯誤,請重新輸入\n");
exit(-1);
}
int length = get_length(argv[1]);
if(length < 0){
printf("srcfile error\n");
return -1;
}
if((pid=fork())==-1){
printf("fork error");
exit(-1);
}else if(pid == 0){
copy_file(argv[1],destfile,length/2,length-length/2);
}else{
copy_file(argv[1],destfile,0,length/2);
}
return 0;
}
三.什么是孤兒進程與僵尸進程
3.1僵尸進程
子進程結束之后,父進程沒有為它回收資源,此時子進程就是僵尸進程
#include <head.h>
int main(int argc, const char* argv[])
{
pid_t pid;
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
//子進程
} else {
//父進程
while(1);
}
return 0;
}
3.2孤兒進程
孤兒進程:父進程死掉之后,子進程就是孤兒進程,孤兒進程被init進程收養(yǎng)。
#include <head.h>
int main(int argc, const char* argv[])
{
pid_t pid;
pid = fork();
if (pid == -1) {
PRINT_ERR("fork error");
} else if (pid == 0) {
//子進程
printf("pid = %d\n",getpid());
while (1);
} else {
//父進程
}
return 0;
}
四,守護進程的創(chuàng)建
4.1守護進程的創(chuàng)建
守護進程:相當于系統(tǒng)的服務,隨著系統(tǒng)的啟動而運行,隨著系統(tǒng)的終止而終止。脫離了某個終端.
4.2步驟圖
4.3代碼實現(xiàn)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#define ERROR(msg) do{\
printf("%s %s %d\n",__FILE__,__func__,__LINE__);\
printf(msg);\
exit(-1); \
}while(0)
int main(int argc, char const *argv[])
{
pid_t pid;
if ((pid == fork()) == -1){
ERROR("fork error");
}else if(pid == 0){
int fd;
setsid();
chdir("/");
umask(0);
for(int i = 3; i < getdtablesize(); i++){
close(i);
}
if((fd = open("my.log", O_RDWR, O_APPEND, O_CREAT, 0666)) == -1){
ERROR("open error");
}
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
while(1){
sleep(1);
printf("我是子進程\n");
fflush(stdout);
}
}else{
printf("父親進程已經(jīng)結束....\n");
exit(-1);
}
return 0;
}
原文鏈接:https://blog.csdn.net/a2998658795/article/details/126324352
相關推薦
- 2022-06-28 C#操作串口通信協(xié)議Modbus的常用方法介紹_C#教程
- 2022-01-30 VSCode標簽內的代碼塊無法折疊問題解決
- 2022-12-03 Golang基于sync.Once實現(xiàn)單例的操作代碼_Golang
- 2022-05-20 SpringBoot整合Mybatis演示
- 2022-12-12 React?中state與props更新深入解析_React
- 2022-10-11 tidb-系統(tǒng)內核調優(yōu)及對比
- 2022-09-16 C#數(shù)據(jù)庫操作的示例詳解_C#教程
- 2022-05-25 Postman動態(tài)獲取值(動態(tài)設置全局變量)
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支