一、進程介紹
進程是指在操作系統中正在運行的一個程序,它在操作系統中佔有一定的資源,如內存、I/O、CPU時間等。
每個進程都有自己的地址空間,互相之間無法訪問,是通過操作系統提供的IPC(進程間通信)機制來進行進程間的通信和數據交互。
在C++中,可以通過一些庫函數來創建和控制進程的運行,如fork()、exec()、wait()等函數。
二、多進程編程
多進程編程是指同時運行多個進程,它可以提高程序的並發性和效率,對於系統性能和響應時間的要求高時非常有用。
在C++中,創建一個新進程可以使用fork()函數,它會複製父進程的所有資源,包括代碼、數據、棧、堆等,然後子進程繼續執行fork()函數後的語句,而父進程則返回子進程的進程ID,這樣父子進程可以在不同的代碼分支中執行不同的任務。
可以通過判斷fork()函數的返回值來確定當前代碼執行的是父進程還是子進程:
pid_t pid = fork(); if (pid == 0) { // 子進程 } else if (pid > 0) { // 父進程 } else { // 出錯處理 }
其中pid_t是一個整型類型,代表進程ID,如果pid等於0,則表示當前代碼執行的是子進程的分支;如果pid大於0,則表示當前代碼執行的是父進程的分支,pid就是子進程的進程ID;如果pid小於0,則表示創建新進程失敗。
除了fork()函數,還可以使用exec系列函數和wait()函數來控制進程的運行。
三、進程間通信
進程間通信(IPC)是指兩個或多個進程之間的數據交換和通信,可以使用多種方式進行進程間通信,常見的有管道、消息隊列、共享內存和信號量等。
其中,管道是最簡單的通信方式,它可以在兩個進程之間傳遞字符流,但只能用於具有親緣關係的進程之間通信(即通過fork()函數創建的父子進程);消息隊列可以傳遞複雜的數據結構,但如果數據量比較大時會影響性能;共享內存可以實現多個進程之間對同一塊內存的訪問,但需要解決進程同步和互斥的問題;信號量可以用來實現進程之間的同步和互斥,但需要掌握一定的信號量編程技巧。
下面是一個使用管道在父子進程之間傳遞數據的例子:
const int BUFFER_SIZE = 1024; int pipe_fd[2]; char message[BUFFER_SIZE]; pid_t pid; if (pipe(pipe_fd) < 0) { std::cerr << "create pipe error." << std::endl; exit(-1); } if ((pid = fork()) == -1) { std::cerr << "fork error." << std::endl; exit(-1); } else if (pid == 0) { close(pipe_fd[1]); // 關閉寫通道 if (read(pipe_fd[0], message, BUFFER_SIZE) == -1) { std::cerr << "read error." << std::endl; exit(-1); } std::cout << "child process received message: " << message << std::endl; close(pipe_fd[0]); // 關閉讀通道 } else { close(pipe_fd[0]); // 關閉讀通道 std::string input_message; std::cout << "input message to be sent to child process: "; std::getline(std::cin, input_message); if (write(pipe_fd[1], input_message.c_str(), input_message.size()) == -1) { std::cerr << "write error." << std::endl; exit(-1); } close(pipe_fd[1]); // 關閉寫通道 wait(NULL); // 等待子進程結束 }
四、進程管理
進程管理是指對操作系統中的進程進行管理和調度,包括創建進程、終止進程、監控進程等操作,常用的進程管理工具有ps、top和kill等。
在C++中,可以使用系統函數kill()來終止一個進程,需要傳入進程ID和終止信號:
if (kill(pid, SIGKILL) == -1) { std::cerr << "kill process error." << std::endl; exit(-1); }
其中,SIGKILL是一個宏定義,代表終止信號。
五、多進程編程實例
下面是一個簡單的多進程ping程序,它可以並行的ping多個IP地址,同時顯示結果:
#include #include #include #include #include #include #include #include #include #include #include const int MAX_PROC_NUM = 10; const int MAX_IP_NUM = 10; const int MAX_RESULT_SIZE = 1024; int proc_num = 0; char ip_list[MAX_IP_NUM][16]; bool ping(const char* ip) { char cmd[1024] = {0}; sprintf(cmd, "ping -c 4 %s", ip); FILE* pipe = popen(cmd, "r"); if (!pipe) { return false; } char buffer[MAX_RESULT_SIZE]; memset(buffer, 0, MAX_RESULT_SIZE); while (!feof(pipe)) { if (fgets(buffer, MAX_RESULT_SIZE, pipe)) { std::cout << buffer; } } if (pclose(pipe) == -1) { return false; } return true; } void handle_signal(int signo) { std::cout << "process " << getpid() << " received signal " << signo << std::endl; exit(signo); } void start_proc(int idx) { const char* ip = ip_list[idx]; std::cout << "start ping " << ip << ", process id " << getpid() << std::endl; if (signal(SIGINT, handle_signal) == SIG_ERR) { std::cerr << "error setting signal handler." << std::endl; exit(-1); } ping(ip); std::cout << "ping " << ip << " finish, process id " << getpid() < 0) { std::cout << "process " << pid << " exit with status " << WEXITSTATUS(status) << std::endl; proc_num--; } } int main(int argc, char* argv[]) { if (argc < 2) { std::cerr << "usage: " << argv[0] << " ip1 [ip2] [...]" < MAX_IP_NUM) { std::cerr << "too many ip addresses." << std::endl; return -1; } for (int i = 0; i < argc - 1; ++i) { strncpy(ip_list[i], argv[i + 1], sizeof(ip_list[i])); } for (int i = 0; i 0) { // parent } else { std::cerr << "fork process error." < 0) { check_procs(); sleep(1); } return 0; }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/235615.html