Cuộc gọi hệ thống ngã ba trong C

Fork System Call C



lệnh gọi hệ thống fork () được sử dụng để tạo các tiến trình con trong một chương trình C. fork () được sử dụng khi cần xử lý song song trong ứng dụng của bạn. Hàm hệ thống fork () được định nghĩa trong tiêu đề sys / type.hunistd.h . Trong một chương trình mà bạn sử dụng fork, bạn cũng phải sử dụng lệnh gọi hệ thống wait (). Lệnh gọi hệ thống wait () được sử dụng để đợi trong tiến trình mẹ kết thúc quá trình con. Để kết thúc một quy trình con, lệnh gọi hệ thống exit () được sử dụng trong quy trình con. Hàm wait () được định nghĩa trong tiêu đề sys / wait.h và hàm exit () được định nghĩa trong tiêu đề stdlib.h .

Hình 1: Quy trình làm việc fork () cơ bản

Hình 1: Quy trình làm việc fork () cơ bản







Trong bài viết này, tôi sẽ chỉ cho bạn cách sử dụng lệnh gọi hệ thống fork () để tạo các quy trình con trong C. Vì vậy, hãy bắt đầu.



fork () Cú pháp và Giá trị Trả lại:

Cú pháp của hàm hệ thống fork () như sau:



ngã ba pid_t(vô hiệu);

Hàm hệ thống fork () không chấp nhận bất kỳ đối số nào. Nó trả về một số nguyên kiểu pid_t .





Khi thành công, fork () trả về PID của tiến trình con lớn hơn 0. Bên trong tiến trình con, giá trị trả về là 0. Nếu fork () không thành công, thì nó trả về -1.

Đơn giản fork () Ví dụ:

Dưới đây là một ví dụ đơn giản về fork ():



#bao gồm
#bao gồm
#bao gồm
#bao gồm
#bao gồm

NSchủ chốt(vô hiệu) {
pid_t pid=cái nĩa();

nếu như(pid== 0) {
printf ('Con => PPID:% d PID:% d ',có được(),người lém lỉnh());
lối ra (EXIT_SUCCESS);
}
khác nếu như(pid> 0) {
printf ('Parent => PID:% d ',người lém lỉnh());
printf ('Đang đợi quá trình con kết thúc. ');
đợi đã(VÔ GIÁ TRỊ);
printf ('Quá trình con đã hoàn tất. ');
}
khác {
printf ('Không thể tạo quy trình con. ');
}

trở lạiEXIT_SUCCESS;
}

Ở đây, tôi đã sử dụng fork () để tạo một quy trình con từ quy trình chính / cha. Sau đó, tôi in PID (Process ID) và PPID (Parent Process ID) từ quy trình con và cha mẹ. Trên tiến trình cha, đợi (NULL) được sử dụng để đợi tiến trình con kết thúc. Trên tiến trình con, exit () được sử dụng để kết thúc tiến trình con. Như bạn có thể thấy, PID của tiến trình mẹ là PPID của tiến trình con. Vì vậy, quá trình con 24738 thuộc về quy trình mẹ 24731 .

Bạn cũng có thể sử dụng các hàm để làm cho chương trình của bạn có nhiều mô-đun hơn. Ở đây, tôi đã sử dụng processTask ()parentTask () các chức năng cho quy trình con và quy trình cha tương ứng. Đây là cách fork () thực sự được sử dụng.

#bao gồm
#bao gồm
#bao gồm
#bao gồm
#bao gồm

vô hiệuchildTask() {
printf ('Chào thế giới ');
}

vô hiệuparentTask() {
printf ('Nhiệm vụ chính. ');
}

NSchủ chốt(vô hiệu) {
pid_t pid=cái nĩa();

nếu như(pid== 0) {
childTask();
lối ra (EXIT_SUCCESS);
}
khác nếu như(pid> 0) {
đợi đã(VÔ GIÁ TRỊ);
parentTask();
}
khác {
printf ('Không thể tạo quy trình con.');
}

trở lạiEXIT_SUCCESS;
}

Kết quả của chương trình trên:

Chạy nhiều quy trình con sử dụng fork () và Loop:

Bạn cũng có thể sử dụng vòng lặp để tạo nhiều tiến trình con tùy ý. Trong ví dụ dưới đây, tôi đã tạo 5 tiến trình con bằng vòng lặp for. Tôi cũng đã in PID và PPID từ các quy trình con.

#bao gồm
#bao gồm
#bao gồm
#bao gồm
#bao gồm

NSchủ chốt(vô hiệu) {
(NStôi= 1;tôi<= 5;tôi++) {
pid_t pid=cái nĩa();

nếu như(pid== 0) {
printf ('Tiến trình con => PPID =% d, PID =% d ',có được(),người lém lỉnh());
lối ra (0);
}
khác {
printf ('Quy trình chính => PID =% d ',người lém lỉnh());
printf ('Đang đợi các quy trình con kết thúc ... ');
đợi đã(VÔ GIÁ TRỊ);
printf ('quy trình con đã hoàn thành. ');
}
}

trở lạiEXIT_SUCCESS;
}

Như bạn có thể thấy, ID quy trình chính giống nhau trong tất cả các quy trình con. Vì vậy, tất cả chúng đều thuộc về cùng một phụ huynh. Chúng cũng thực hiện theo kiểu tuyến tính. Cái này sau cái kia. Kiểm soát các quá trình trẻ em là một nhiệm vụ phức tạp. Nếu bạn tìm hiểu thêm về lập trình hệ thống Linux và cách nó hoạt động, bạn sẽ có thể kiểm soát luồng của các quy trình này theo cách nào bạn muốn.

Ví dụ trong cuộc sống thực:

Các phép tính toán học phức tạp khác nhau như md5, sha256, vv tạo băm yêu cầu rất nhiều sức mạnh xử lý. Thay vì tính toán những thứ như vậy trong cùng một quy trình với chương trình chính, bạn chỉ có thể tính toán băm trên một quy trình con và trả lại băm cho quy trình chính.

Trong ví dụ sau, tôi đã tạo mã PIN gồm 4 chữ số trong quy trình con và gửi mã đó đến quy trình mẹ, chương trình chính. Sau đó, tôi in mã PIN từ đó.

#bao gồm
#bao gồm
#bao gồm
#bao gồm
#bao gồm

NSgetPIN() {
// sử dụng PPID và PID làm hạt giống
srand (người lém lỉnh() +có được());
NSbí mật= 1000 + hàng ngang () % 9000;
trở lạibí mật;
}

NSchủ chốt(vô hiệu) {
NSfd[2];
đường ống(fd);
pid_t pid=cái nĩa();

nếu như(pid> 0) {
gần(0);
gần(fd[1]);
sau(fd[0]);

NScon số bí mật;
size_treadBytes=đọc(fd[0], &con số bí mật, kích thước(con số bí mật));

printf ('Đang đợi mã PIN ... ');
đợi đã(VÔ GIÁ TRỊ);
printf ('Số byte đã đọc:% ld ',readBytes);
printf ('Mã PIN:% d ',con số bí mật);
}
khác nếu như(pid== 0) {
gần(1);
gần(fd[0]);
sau(fd[1]);

NSbí mật=getPIN();
viết(fd[1], &bí mật, kích thước(bí mật));
lối ra (EXIT_SUCCESS);
}

trở lạiEXIT_SUCCESS;
}

Như bạn thấy, mỗi lần tôi chạy chương trình, tôi nhận được một mã PIN gồm 4 chữ số khác nhau.

Vì vậy, về cơ bản đó là cách bạn sử dụng lệnh gọi hệ thống fork () trong Linux. Cảm ơn đã đọc bài viết này.