Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình C

Làm chủ fork() và exec() trong C: Tạo và thay thế tiến trình

Bài viết Linuxhint này hướng dẫn dùng fork() và exec() để tạo, chạy hoặc thay thế tiến trình. Chúng ta xem mô tả, cú pháp, cách gọi và ví dụ thực tế cho từng hàm, sau đó kết hợp fork() và execv() để tạo tiến trình mới và thay thế nó.

Hàm fork() trong C

fork() tạo bản sao của tiến trình gọi. Tiến trình con là bản sao của cha, nhưng không chia sẻ vùng nhớ đã cấp phát, PID, v.v. Cú pháp:

pid_t fork(void);

fork() trả về PID của tiến trình con trong tiến trình cha, và trả về 0 trong tiến trình con. Cơ chế này cho phép chạy code khác nhau trong hai tiến trình qua điều kiện if (fork() == 0).

if (fork() == 0) {
    // code cho tiến trình con
} else {
    // code cho tiến trình cha
}

Ví dụ đơn giản

Hai vòng lặp vô tận: cha in "Write by parent process" mỗi 2 giây, con in "Write by child process" mỗi 5 giây.

#include <stdio.h>
#include <unistd.h>

void main() {
    if (fork() == 0) {
        while (1) {
            printf("Write by child process \n");
            sleep(5);
        }
    } else {
        while (1) {
            printf("Write by parent process \n");
            sleep(2);
        }
    }
}

Làm chủ fork() và exec() trong C: Tạo và thay thế tiến trình

Hàm execXXX()

Họ hàm execXXX() thay thế tiến trình đang chạy bằng tiến trình mới. Hình ảnh tiến trình mới được nạp vào vùng nhớ của tiến trình cũ, giữ nguyên PID và tài nguyên. Các hàm (khai báo trong unistd.h) có cách gọi khác nhau:

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[]);
  • execl, execle, execv dùng đường dẫn tuyệt đối.
  • execlp, execvp, execvpe dùng tên tệp trong thư mục hiện tại (tìm trong PATH).
  • Tham số thứ hai là danh sách đối số truyền cho tiến trình mới (chuỗi hoặc mảng con trỏ chuỗi).

Ví dụ: execv() truyền đối số

Tạo hai chương trình: tiến trình cha gọi execv() chạy tiến trình con, truyền hai đối số.

Tiến trình con (child.c)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    printf("I am the child process\n\n");
    printf("Argument 1: %s\n", argv[1]);
    printf("Argument 2: %s\n", argv[2]);
    return 0;
}

Biên dịch: gcc Documents/child.c -o Documents/child.bin

Tiến trình cha (parent.c)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main() {
    printf("I am the parent process");
    char *arg_Ptr[4];
    arg_Ptr[0] = "child.bin";      // tên chương trình
    arg_Ptr[1] = " Hello from ";
    arg_Ptr[2] = " process 2 ";
    arg_Ptr[3] = NULL;             // kết thúc mảng

    execv("/home/linuxhint/Documents/child.bin", arg_Ptr);
    return 0;
}

Biên dịch: gcc Documents/parent.c -o pattern. Chạy ./pattern.

Làm chủ fork() và exec() trong C: Tạo và thay thế tiến trình

Nếu execv() thành công, tiến trình con thay thế hoàn toàn tiến trình cha (không thể quay lại).

Kết hợp fork() và execve()

Kết hợp cả hai: fork() tạo bản sao, execv() thay thế bản sao đó bằng chương trình child.bin.

#include <stdio.h>
#include <unistd.h>

void main() {
    if (fork() == 0) {
        printf("I am the child process\n");
        char *arg_Ptr[5];
        arg_Ptr[0] = "child.bin";
        arg_Ptr[1] = " Hello from ";
        arg_Ptr[2] = " process 2 ";
        arg_Ptr[3] = NULL;
        execv("/home/linuxhint/Documents/child.bin", arg_Ptr);
    } else {
        while (1) {
            printf("Write by parent process \n");
            sleep(3);
        }
    }
}

Làm chủ fork() và exec() trong C: Tạo và thay thế tiến trình

Kết luận

Bài viết đã trình bày fork() (tạo bản sao tiến trình) và execv() (thay thế tiến trình), cú pháp, tham số, ví dụ riêng lẻ và kết hợp để tạo tiến trình mới trên Linux.