Bạn đã bao giờ nghe nói về Định luật Moore điều chỉnh ngành công nghiệp bán dẫn trong gần 60 năm chưa? Bạn có biết rằng Quy tắc Moore không bao giờ là một định luật, mà là một quan sát? Đối với những người không quen thuộc với luật này, đây là cách nó được thể hiện.
Định luật Moore quan sát thấy rằng số lượng bóng bán dẫn trong các mạch tích hợp dày đặc tăng gấp đôi sau mỗi hai năm.
Mặc dù quy tắc được viết dưới góc độ điện tử, nhưng từ quan điểm của máy tính, nó chỉ ra rằng sức mạnh tính toán sẽ tăng gấp đôi sau mỗi hai năm. Về cơ bản, sức mạnh tính toán trên một con chip tăng lên theo cấp số nhân. Thật tuyệt vời phải không?
Điều đáng kinh ngạc là kể từ khi quan sát này được thực hiện, nó đã được chứng minh là đúng và bây giờ được coi là một quy luật.
Tuy nhiên, như tất cả chúng ta đều nhận thức được, những điều tốt đẹp không phải lúc nào cũng miễn phí. Trong trường hợp này, việc tính toán mạnh mẽ hơn đã phải trả giá bằng nhiệt độ quá cao. Vào thời điểm họ đến vào năm 2010, các nhà chế biến đã đạt đến nhiệt độ đủ cao để nấu mì ống. (Xem video youtube này để tự mình trải nghiệm).
Ngoài ra, khi số lượng bóng bán dẫn trên chip tăng lên, các giới hạn vật lý của vật liệu bắt đầu đạt đến. Các lực hạ nguyên tử bắt đầu hoạt động vào thời điểm này, khiến việc duy trì quỹ đạo của định luật Moore trở nên khó khăn.
Có vẻ như thời kỳ tốt đẹp đã qua khi máy tính trở nên nhanh hơn bao giờ hết. Nhưng các kỹ sư đã có kế hoạch khác. Họ bắt đầu sử dụng nhiều lõi mạnh mẽ thay vì một lõi siêu mạnh duy nhất.
Mặc dù nó có thể đã giải quyết được vấn đề phần cứng, nhưng nó lại đưa ra một thách thức mới đối với các kỹ sư phần mềm. Các kỹ sư đã phải phát triển phần mềm tận dụng một số lõi mà máy tính hiện nay có. Kết quả là lập trình đồng thời, thường được gọi là lập trình song song, đã ra đời. Chủ đề đang được chú ý trong lĩnh vực lập trình này. Nhưng trước khi nói về chủ đề, chúng ta phải hiểu quy trình là gì.
Quy trình Linux được định nghĩa là một phiên bản đang chạy của một chương trình.
Do đó, hệ thống phải theo dõi một số mục trong khi một chương trình được thực hiện, bao gồm bộ nhớ ngăn xếp, mã nguồn và thanh ghi, cùng những thứ khác. Trong Linux, tổng hợp của tất cả những thứ này được gọi là một quá trình. Linux được xây dựng trên nền tảng của các quy trình.
Để kiểm tra các quy trình khác nhau đang chạy trên máy của bạn, bạn có thể thử chạy lệnh sau. Điều này sẽ chạy tất cả các quy trình cùng với ID quy trình của chúng.
$ ps
Đây là một ảnh chụp nhanh mẫu.
Theo mặc định, lệnh trên chỉ hiển thị những quy trình được liên kết với người dùng hiện tại. Để liệt kê tất cả các quá trình, chúng ta có thể sử dụng lệnh với các tùy chọn sau.
$ ps -aux
Đây là một ảnh chụp nhanh mẫu.
Việc áp dụng các tùy chọn bổ sung này cho lệnh ps
cũng cung cấp cho chúng ta một số thông tin bổ sung. Đây là ý nghĩa của các lá cờ khác nhau -
a
đại diện cho tất cả người dùngu
đại diện cho người dùng hiện tạix
hiển thị quá trình được thực hiện bên ngoài thiết bị đầu cuối
Chúng ta cũng có thể giết một số tiến trình bằng cách sử dụng lệnh kill
. Đây là cách nó được sử dụng -
$ kill PID
Ở đây PID
là ID tiến trình mà chúng ta có thể lấy từ lệnh ps
. Mỗi tiến trình trong hệ thống Linux sẽ có một PID
duy nhất được sử dụng để xác định nó. Bạn thậm chí có thể sử dụng lệnh pidof
để tìm PID
của quá trình.
$ pidof bash
Khi bạn khởi chạy một chương trình hoặc ra lệnh, một quá trình sẽ được hình thành. Khi bạn thực hiện một lệnh từ thiết bị đầu cuối, bạn bắt đầu một quy trình mới. Bởi vì một thiết bị đầu cuối đã được sử dụng để tạo ra quy trình mới này, chúng tôi nói rằng quy trình đầu cuối đã bắt đầu quy trình lệnh mới. Nói cách khác, tiến trình lệnh mới là con của tiến trình đầu cuối.
Mọi quy trình trong hệ sinh thái Linux đều có quy trình mẹ tạo ra nó. Chúng ta có thể sử dụng lệnh sau để kiểm tra quy trình mẹ của một quy trình với PID
đã cho.
$ ps -o ppid= -p PID
Tất cả các quy trình trong Linux, trực tiếp hoặc gián tiếp, đều là con của quy trình với PID 1. Đây không phải là một sự trùng hợp ngẫu nhiên. Quá trình với PID 1 là quá trình init và là quá trình đầu tiên được hệ thống bắt đầu tại thời điểm khởi động. Bất kỳ quy trình tiếp theo nào được tạo ra dưới dạng con của quy trình này.
Do đó, chúng tôi có một cây được xây dựng từ các mối quan hệ này giữa các quy trình. Đây được gọi là cây quy trình.
Các quy trình cực kỳ hữu ích trong Linux và chúng tôi không thể sống thiếu chúng. Nhưng có một nhược điểm đối với chúng, hoặc có lẽ không phải là nhược điểm gì cả, mà chỉ là cách chúng hoạt động. Một thủ tục là nặng nề. Dữ liệu, bộ nhớ và các biến được chuyển bất cứ khi nào một quy trình mới được khởi chạy. Mỗi tiến trình chạy cùng một chương trình sẽ có bản sao mã nguồn của riêng nó. Do đó, việc tạo ra một số lượng lớn các quy trình không phải là một ý tưởng thông minh.
Tuy nhiên, bởi vì các quy trình là một cơ chế để phục vụ một số yêu cầu cùng một lúc, chúng tôi bị hạn chế bởi sự thật khó chịu này. Chúng tôi chỉ có thể phục vụ một số lượng nhỏ người dùng đồng thời có nhiều điểm chung vì chúng tôi chỉ có thể khởi chạy một số quy trình hạn chế trong hệ thống của mình. Hãy xem xét một máy chủ web phải phục vụ nhiều người dùng đồng thời. Tạo một quy trình mới cho mỗi người dùng là một hoạt động tốn kém. Kết quả là, chúng tôi muốn một cái gì đó ít tốn kém hơn so với thủ tục. Chủ đề có hiệu lực ở đây.
Chủ đề chỉ là các quy trình nhẹ. Một luồng chia sẻ bộ nhớ với tiến trình cha của nó và bất kỳ luồng nào mà nó đã tạo. Do bộ nhớ được chia sẻ này, việc tạo ra các chủ đề mới sẽ ít tốn kém hơn. Điều này cung cấp thêm lợi ích của giao tiếp luồng nhanh hơn và chuyển đổi ngữ cảnh. Sử dụng các luồng, một quy trình có thể thực hiện một số tác vụ đồng thời.
So với số lượng quy trình, chúng ta có thể tạo ra một số lượng đáng kể các luồng. Trên nhiều máy lõi, các luồng này được thực hiện song song. Khi trái ngược với việc tạo ra nhiều quy trình hoặc thực hiện tất cả các tác vụ một cách tuần tự, điều này sẽ cải thiện hiệu suất tổng thể của chương trình.
Hãy cố gắng bắt đầu chủ đề đầu tiên của chúng tôi. Điều quan trọng cần lưu ý là chúng ta không thể bắt đầu chủ đề mới với bash. Lệnh bash chỉ có thể được sử dụng để tạo các quy trình con. Vì vậy, những gì chúng ta sẽ làm là viết một mã C khởi chạy hai luồng. Sau đó, sử dụng bash, chúng tôi sẽ thực thi mã C này như một quy trình con. Sau đó, hai luồng sẽ được tạo bởi quy trình mới này.
Hãy để chúng tôi bắt đầu tìm kiếm một số mã. Tạo một tệp mới và đặt tên là threads.c
. Hãy tiếp tục và mở nó bằng bất kỳ IDE nào bạn yêu thích.
Bước đầu tiên là nhập các tệp tiêu đề cần thiết.
#include <pthread.h> #include <stdio.h>
Chúng ta sẽ tạo hai luồng, mỗi luồng thực hiện cùng một chức năng nhưng với các tham số khác nhau. Hãy để chúng tôi viết hàm đó.
void* print_multiple_messages(void* ptr) { char* message = (char*) ptr; for(int i=0; i<1000; ++i) { printf("%s \n", message); } }
Như bạn có thể thấy, chức năng này không có gì to tát. Nó nhận một thông báo làm tham số đầu vào và in ra hàng nghìn lần.
Bây giờ chúng ta hãy viết hàm chính.
int main() { // Continue writing from here }
Cũng giống như các quy trình, các luồng cũng có ID được sử dụng để xác định duy nhất chúng. Tạo hai biến để giữ các ID này.
pthread_t thread1, thread2;
Chúng tôi sẽ sử dụng các thông điệp khác nhau cho mỗi chủ đề. Tạo hai chuỗi (mảng ký tự) để chứa các thông điệp khác nhau.
char* message1 = "Thread 1"; char* message2 = "Thread 2";
Bước tiếp theo là tạo hai chủ đề. Chúng tôi sẽ sử dụng phương thức pthread_create
để làm điều đó.
pthread_create(&thread1, NULL, print_multiple_messages, (void*) message1); pthread_create(&thread2, NULL, print_multiple_messages, (void*) message2);
Điều này sẽ bắt đầu hai chủ đề mới. Hãy để chúng tôi hướng dẫn quy trình chính của chúng tôi đợi cho đến khi hai luồng hoàn thành công việc của chúng.
pthread_join(thread1, NULL); pthread_join(thread2, NULL);
Và đó là nó. Biên dịch mã và thực thi nó. Bạn sẽ nhận thấy rằng các tin nhắn từ hai chuỗi sẽ được trộn lẫn với nhau. Điều này cho thấy chúng đang được thực hiện song song.
Xin chúc mừng bạn vừa tạo chủ đề đầu tiên của mình.
Vì vậy, trong bài viết này, chúng tôi đã nói về Chủ đề và Quy trình. Đây là một số tính năng hấp dẫn nhất của Linux và việc thành thạo chúng là rất quan trọng. Nó cho phép phát triển phần mềm nhận biết phần cứng và sử dụng hiệu quả các tài nguyên theo ý của chúng ta.
Ở đây, chúng tôi sẽ đưa ra kết luận cho bài viết này. Chúng tôi đã cố gắng đi vào đủ chi tiết để giúp bạn tiếp tục, nhưng không phải vậy. Vì vậy, hãy tiếp tục học hỏi thêm. Nếu bạn thích nội dung, bạn có thể muốn nhận xét và / hoặc biểu tượng cảm xúc.
Hãy tận hưởng việc học!