一、進程介紹
進程是指在操作系統中正在運行的一個程序,它在操作系統中佔有一定的資源,如內存、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
微信掃一掃
支付寶掃一掃