Trăn có vm không?
Hoạt động nội bộ của Python Show
Cải thiện bài viết Lưu bài viết Thích bài viết
Cải thiện bài viết Lưu bài viết Python là một ngôn ngữ lập trình hướng đối tượng như Java. Python được gọi là ngôn ngữ thông dịch. Python sử dụng các mô-đun mã có thể hoán đổi cho nhau thay vì một danh sách dài các hướng dẫn là tiêu chuẩn cho các ngôn ngữ lập trình chức năng. Việc triển khai tiêu chuẩn của python được gọi là “cpython”. Đây là triển khai mặc định và được sử dụng rộng rãi của Python. Mã nguồn Python đi qua phần sau để tạo mã thực thi.
Người giới thiệu. Ghi chú cá nhân của tôi arrow_drop_up Cứu Vui lòng Đăng nhập để nhận xét.Chúng tôi biết rằng máy tính chỉ hiểu mã máy bao gồm 1 và 0. Vì máy tính chỉ hiểu mã máy, nên bắt buộc chúng ta phải chuyển đổi bất kỳ chương trình nào thành mã máy trước khi gửi cho máy tính để thực thi. Với mục đích này, chúng ta nên nhờ sự trợ giúp của trình biên dịch. Trình biên dịch thường chuyển đổi mã nguồn chương trình thành mã máy Trình biên dịch Python thực hiện nhiệm vụ tương tự nhưng theo một cách hơi khác. Nó chuyển đổi mã nguồn chương trình thành mã khác, được gọi là mã byte. Mỗi câu lệnh chương trình Python được chuyển đổi thành một nhóm các lệnh mã byte. Vậy mã byte là gì? . Kích thước của mỗi lệnh mã byte là 1 byte (hoặc 8 bit) và do đó chúng được gọi là lệnh mã byte. Tổ chức Python nói rằng thỉnh thoảng có thể có các hướng dẫn mới hơn được thêm vào các hướng dẫn mã byte hiện có. Chúng ta có thể tìm thấy hướng dẫn mã byte trong. tập tin pyc. Hình dưới đây cho thấy vai trò của máy ảo trong việc chuyển đổi các lệnh mã byte thành mã máy Vai trò của Máy ảo Python (PVM) là chuyển đổi các lệnh mã byte thành mã máy để máy tính có thể thực thi các lệnh mã máy đó và hiển thị đầu ra cuối cùng. Để thực hiện việc chuyển đổi này, PVM được trang bị máy phiên dịch. Trình thông dịch chuyển mã byte thành mã máy và gửi mã máy đó tới bộ xử lý máy tính để thực thi. Vì trình thông dịch đóng vai trò chính nên thường Máy ảo Python còn được gọi là trình thông dịch Bài báo này mở ra một loạt bài tìm cách trả lời chính câu hỏi này. Chúng ta sẽ đi sâu vào nội dung bên trong của CPython, triển khai phổ biến nhất của Python. Bằng cách đó, chúng ta sẽ hiểu ngôn ngữ ở mức độ sâu hơn. Đó là mục tiêu chính của loạt bài này. Nếu bạn quen thuộc với Python và đọc C thoải mái nhưng không có nhiều kinh nghiệm làm việc với mã nguồn của CPython, rất có thể bạn sẽ thấy bài viết này thú vị CPython là gì và tại sao mọi người muốn nghiên cứu nóHãy bắt đầu bằng cách nêu một số sự thật nổi tiếng. CPython là một trình thông dịch Python được viết bằng C. Đây là một trong những triển khai Python, cùng với PyPy, Jython, IronPython và nhiều ứng dụng khác. CPython được phân biệt ở chỗ nó là bản gốc, được bảo trì nhiều nhất và phổ biến nhất CPython triển khai Python, nhưng Python là gì? . Câu trả lời trở nên sắc thái hơn nhiều khi cùng một câu hỏi được đặt đúng. điều gì định nghĩa Python là gì? . Thứ gần nhất với nó là Tham chiếu ngôn ngữ Python bắt đầu bằng các từ sau
Vì vậy, Python không chỉ được xác định bởi tham chiếu ngôn ngữ của nó. Cũng sẽ sai khi nói rằng Python được xác định bởi triển khai tham chiếu của nó, CPython, vì có một số chi tiết triển khai không phải là một phần của ngôn ngữ. Trình thu gom rác dựa trên số tham chiếu là một ví dụ. Vì không có nguồn sự thật duy nhất, chúng tôi có thể nói rằng Python được xác định một phần bởi Tham chiếu ngôn ngữ Python và một phần bởi triển khai chính của nó, CPython Lập luận như vậy có vẻ khoa trương, nhưng tôi nghĩ điều quan trọng là phải làm rõ vai trò chính của chủ đề chúng ta sẽ nghiên cứu. Tuy nhiên, bạn có thể vẫn thắc mắc tại sao chúng ta nên nghiên cứu nó. Bên cạnh sự tò mò đơn thuần, tôi thấy những lý do sau
Cần những gì để hiểu cách thức hoạt động của CPythonCPython được thiết kế để dễ bảo trì. Một người mới chắc chắn có thể mong đợi có thể đọc mã nguồn và hiểu nó làm gì. Tuy nhiên, nó có thể mất một thời gian. Bằng cách viết loạt bài này, tôi hy vọng sẽ giúp bạn rút ngắn nó Làm thế nào loạt bài này được đặt raTôi chọn cách tiếp cận từ trên xuống. Trong phần này, chúng ta sẽ khám phá các khái niệm cốt lõi của máy ảo CPython (VM). Tiếp theo, chúng ta sẽ xem cách Python biên dịch chương trình thành thứ gì đó mà VM có thể thực thi. Sau đó, chúng ta sẽ làm quen với mã nguồn và từng bước thực hiện một chương trình đang nghiên cứu các phần chính của trình thông dịch. Cuối cùng, chúng ta sẽ có thể chọn ra từng khía cạnh khác nhau của ngôn ngữ và xem chúng được triển khai như thế nào. Đây không phải là một kế hoạch nghiêm ngặt mà là ý tưởng gần đúng của tôi Ghi chú. Trong bài viết này tôi đang đề cập đến CPython 3. 9. Một số chi tiết triển khai chắc chắn sẽ thay đổi khi CPython phát triển. Tôi sẽ cố gắng theo dõi những thay đổi quan trọng và thêm ghi chú cập nhật bức tranh lớnQuá trình thực thi chương trình Python bao gồm ba giai đoạn
Trong giai đoạn khởi tạo, CPython khởi tạo cấu trúc dữ liệu cần thiết để chạy Python. Nó cũng chuẩn bị những thứ như kiểu tích hợp, định cấu hình và tải các mô-đun tích hợp, thiết lập hệ thống nhập và thực hiện nhiều việc khác. Đây là công đoạn rất quan trọng nhưng thường bị các nhà thám hiểm CPython bỏ qua vì tính chất dịch vụ của nó Tiếp đến là giai đoạn tổng hợp. CPython là một trình thông dịch, không phải trình biên dịch theo nghĩa là nó không tạo ra mã máy. Tuy nhiên, các trình thông dịch thường dịch mã nguồn thành một số biểu diễn trung gian trước khi thực thi nó. CPython cũng vậy. Giai đoạn dịch thuật này thực hiện những điều tương tự mà một trình biên dịch điển hình thực hiện. phân tích cú pháp mã nguồn và xây dựng AST (Cây cú pháp trừu tượng), tạo mã byte từ AST và thậm chí thực hiện một số tối ưu hóa mã byte Trước khi xem giai đoạn tiếp theo, chúng ta cần hiểu bytecode là gì. Bytecode là một loạt các hướng dẫn. Mỗi lệnh bao gồm hai byte. một cho một opcode và một cho một đối số. Hãy xem xét một ví dụ
CPython dịch phần thân của hàm 1 thành chuỗi byte sau. 2. Nếu chúng tôi chạy mô-đun 3 tiêu chuẩn để tháo rời nó, đây là những gì chúng tôi sẽ nhận được
Opcode 4 tương ứng với byte 5 và có đối số 6. Opcode 7 tương ứng với byte 8 và có đối số 9. Các lệnh 0 và 1 luôn được mã hóa lần lượt là 2 và 3 vì chúng không cần đối sốTrung tâm của CPython là một máy ảo thực thi mã byte. Bằng cách nhìn vào ví dụ trước, bạn có thể đoán nó hoạt động như thế nào. Máy ảo của CPython dựa trên ngăn xếp. Có nghĩa là nó thực thi các lệnh sử dụng ngăn xếp để lưu trữ và truy xuất dữ liệu. Lệnh 4 đẩy một biến cục bộ lên ngăn xếp. 7 đẩy một hằng số. 0 lấy hai đối tượng ra khỏi ngăn xếp, cộng chúng lại và đẩy kết quả trở lại. Cuối cùng, 1 bật bất cứ thứ gì trong ngăn xếp và trả kết quả cho người gọi nóViệc thực thi mã byte diễn ra trong một vòng lặp đánh giá khổng lồ chạy trong khi có hướng dẫn để thực thi. Nó dừng lại để mang lại một giá trị hoặc nếu xảy ra lỗi Một tổng quan ngắn gọn như vậy làm phát sinh rất nhiều câu hỏi
Để trả lời những câu hỏi này và những câu hỏi hấp dẫn khác, chúng ta cần xem xét các khái niệm cốt lõi của CPython VM Đối tượng mã, đối tượng chức năng, khungđối tượng mãChúng ta đã thấy mã byte của một hàm đơn giản trông như thế nào. Nhưng một chương trình Python điển hình phức tạp hơn. Làm thế nào để VM thực thi một mô-đun chứa các định nghĩa hàm và thực hiện các lệnh gọi hàm? Xem xét chương trình
Mã byte của nó trông như thế nào? . Nó định nghĩa hàm 1, gọi 1 với đối số là ___0_______9 và in kết quả của cuộc gọi. Dù chức năng 1 làm gì, nó không phải là một phần của mã byte của mô-đun. Chúng ta có thể tự đảm bảo bằng cách chạy trình dịch ngược
Ở dòng 1, chúng ta định nghĩa hàm 1 bằng cách tạo hàm từ một thứ gọi là đối tượng mã và gắn tên 6 cho nó. Chúng tôi không thấy mã byte của hàm 1 trả về một đối số tăng dầnCác đoạn mã được thực thi dưới dạng một đơn vị như mô-đun hoặc thân hàm được gọi là khối mã. CPython lưu trữ thông tin về chức năng của một khối mã trong một cấu trúc được gọi là đối tượng mã. Nó chứa mã byte và những thứ như danh sách tên của các biến được sử dụng trong khối. Để chạy một mô-đun hoặc gọi một hàm có nghĩa là bắt đầu đánh giá một đối tượng mã tương ứng đối tượng chức năngTuy nhiên, một chức năng không chỉ đơn thuần là một đối tượng mã. Nó phải bao gồm thông tin bổ sung như tên hàm, chuỗi tài liệu, đối số mặc định và giá trị của các biến được xác định trong phạm vi kèm theo. Thông tin này, cùng với một đối tượng mã, được lưu trữ bên trong một đối tượng chức năng. Lệnh 8 được sử dụng để tạo nó. Định nghĩa về cấu trúc đối tượng chức năng trong mã nguồn CPython được đặt trước bởi nhận xét sau
Làm thế nào mà một số đối tượng chức năng có thể tham chiếu đến một đối tượng mã duy nhất?
Mã byte của hàm 9 chứa lệnh 8. Các hàm 1 và 2 là kết quả của việc gọi hướng dẫn này với cùng một đối tượng mã làm đối số. Nhưng có một đối số khác – giá trị của 0. Mỗi chức năng có riêng nó theo cơ chế của các biến ô cho phép chúng ta tạo các bao đóng như 1 và 2Trước khi chúng ta chuyển sang khái niệm tiếp theo, hãy xem các định nghĩa về mã và các đối tượng chức năng để hiểu rõ hơn về chúng là gì
đối tượng khungKhi VM thực thi một đối tượng mã, nó phải theo dõi các giá trị của biến và ngăn xếp giá trị thay đổi liên tục. Nó cũng cần nhớ nơi nó dừng thực thi đối tượng mã hiện tại để thực thi đối tượng khác và nơi tiếp tục quay trở lại. CPython lưu trữ thông tin này bên trong một đối tượng khung hoặc đơn giản là một khung. Khung cung cấp trạng thái trong đó đối tượng mã có thể được thực thi. Vì chúng ta đã quen với mã nguồn hơn, nên tôi cũng để định nghĩa về đối tượng khung ở đây
Khung đầu tiên được tạo để thực thi đối tượng mã của mô-đun. CPython tạo một khung mới bất cứ khi nào nó cần thực thi một đối tượng mã khác. Mỗi khung có một tham chiếu đến khung trước đó. Do đó, các khung tạo thành một chồng khung, còn được gọi là ngăn xếp cuộc gọi, với khung hiện tại nằm trên cùng. Khi một chức năng được gọi, một khung mới được đẩy vào ngăn xếp. Khi trở về từ khung hiện đang thực thi, CPython tiếp tục thực hiện khung trước đó bằng cách ghi nhớ lệnh được xử lý cuối cùng của nó. Theo một nghĩa nào đó, CPython VM không làm gì ngoài việc xây dựng và thực thi các khung. Tuy nhiên, như chúng ta sẽ sớm thấy, bản tóm tắt này, nói một cách nhẹ nhàng, che giấu một số chi tiết Chủ đề, trình thông dịch, thời gian chạyChúng ta đã xem xét ba khái niệm quan trọng
CPython có thêm ba
trạng thái chủ đềTrạng thái luồng là cấu trúc dữ liệu chứa dữ liệu dành riêng cho luồng bao gồm ngăn xếp cuộc gọi, trạng thái ngoại lệ và cài đặt gỡ lỗi. Không nên nhầm lẫn với một chuỗi hệ điều hành. Chúng được kết nối chặt chẽ, mặc dù. Xem xét điều gì sẽ xảy ra khi bạn sử dụng mô-đun 6 tiêu chuẩn để chạy một chức năng trong một chuỗi riêng biệt
7 thực sự tạo ra một luồng hệ điều hành mới bằng cách gọi hàm OS ( 8 trên các hệ thống giống UNIX và 9 trên Windows). Chuỗi mới được tạo gọi hàm từ mô-đun 0 chịu trách nhiệm gọi mục tiêu. Hàm này không chỉ nhận được mục tiêu và các đối số của mục tiêu mà còn nhận được trạng thái luồng mới sẽ được sử dụng trong luồng hệ điều hành mới. Một luồng hệ điều hành đi vào vòng đánh giá với trạng thái luồng riêng của nó, do đó luôn có sẵn luồng đóChúng ta có thể nhớ ở đây GIL (Khóa phiên dịch toàn cầu) nổi tiếng ngăn chặn nhiều luồng trong vòng đánh giá cùng một lúc. Lý do chính cho điều đó là để bảo vệ trạng thái của CPython khỏi tham nhũng mà không đưa ra các khóa chi tiết hơn. Tham chiếu API Python/C giải thích rõ ràng về GIL
Để quản lý nhiều luồng, cần có cấu trúc dữ liệu cấp cao hơn trạng thái luồng trình thông dịch và trạng thái thời gian chạyTrên thực tế, có hai người trong số họ. trạng thái trình thông dịch và trạng thái thời gian chạy. Sự cần thiết cho cả hai có thể không rõ ràng ngay lập tức. Tuy nhiên, việc thực thi bất kỳ chương trình nào cũng có ít nhất một phiên bản của mỗi chương trình và có những lý do chính đáng cho điều đó Trạng thái trình thông dịch là một nhóm các luồng cùng với dữ liệu dành riêng cho nhóm này. Các chủ đề chia sẻ những thứ như mô-đun đã tải (_______32_______1), nội trang ( 2) và hệ thống nhập ( 3)Trạng thái thời gian chạy là một biến toàn cục. Nó lưu trữ dữ liệu cụ thể cho một quá trình. Điều này bao gồm trạng thái của CPython (e. g. nó có được khởi tạo hay không?) và cơ chế GIL Thông thường, tất cả các luồng của một quy trình đều thuộc về cùng một trình thông dịch. Tuy nhiên, có một số trường hợp hiếm gặp khi một người có thể muốn tạo một trình thông dịch con để cô lập một nhóm luồng. , sử dụng các trình thông dịch riêng biệt để chạy các ứng dụng WSGI, là một ví dụ. Hiệu quả rõ ràng nhất của sự cô lập là mỗi nhóm luồng có phiên bản riêng của tất cả các mô-đun bao gồm 4, là một không gian tên chungCPython không cung cấp một cách dễ dàng để tạo trình thông dịch mới tương tự như mô-đun 6. Tính năng này chỉ được hỗ trợ thông qua API Python/C, nhưng điều này có thể thay đổi vào một ngày nào đótóm tắt kiến trúcHãy tóm tắt nhanh kiến trúc của CPython để xem mọi thứ khớp với nhau như thế nào. Trình thông dịch có thể được xem như một cấu trúc phân lớp. Sau đây tổng hợp các lớp là gì
Các lớp được biểu diễn bằng các cấu trúc dữ liệu tương ứng mà chúng ta đã thấy. Trong một số trường hợp, chúng không tương đương, mặc dù. Ví dụ, cơ chế cấp phát bộ nhớ được thực hiện bằng các biến toàn cục. Nó không phải là một phần của trạng thái thời gian chạy nhưng chắc chắn là một phần của lớp thời gian chạy Phần kết luậnTrong phần này, chúng tôi đã phác thảo những gì 0 thực hiện để thực thi chương trình Python. Chúng tôi đã thấy rằng nó hoạt động trong ba giai đoạn
Phần trình thông dịch chịu trách nhiệm thực thi mã byte được gọi là máy ảo. CPython VM có một số khái niệm đặc biệt quan trọng. đối tượng mã, đối tượng khung, trạng thái luồng, trạng thái trình thông dịch và thời gian chạy. Các cấu trúc dữ liệu này tạo thành cốt lõi của kiến trúc CPython Chúng tôi chưa đề cập đến nhiều thứ. Chúng tôi tránh đào sâu vào mã nguồn. Các giai đoạn khởi tạo và biên dịch hoàn toàn nằm ngoài phạm vi của chúng tôi. Thay vào đó, chúng tôi bắt đầu với tổng quan về VM. Theo tôi, có như vậy chúng ta mới thấy rõ hơn trách nhiệm của từng khâu. Bây giờ chúng ta biết CPython biên dịch mã nguồn thành gì – thành đối tượng mã. Lần tới chúng ta sẽ xem nó làm điều đó như thế nào Nếu bạn có bất kỳ câu hỏi, nhận xét hoặc đề xuất nào, vui lòng liên hệ với tôi theo địa chỉ victor@tenthousandmeters. com Cập nhật từ ngày 4 tháng 9 năm 2020. Tôi đã tạo một danh sách các tài nguyên mà tôi đã sử dụng để tìm hiểu về nội bộ CPython Python có thứ gì giống như JVM không?Máy ảo tiến trình đơn giản là một chương trình cung cấp môi trường lập trình chung -- một chương trình có thể được lập trình. Java có trình thông dịch cũng như máy ảo và Python có máy ảo cũng như trình thông dịch .
Máy ảo Python làm gì?Vai trò của Máy ảo Python (PVM) là chuyển đổi hướng dẫn mã byte thành mã máy để máy tính có thể thực thi các hướng dẫn mã máy đó và hiển thị đầu ra cuối cùng.
Làm cách nào để tạo một máy ảo trong Python?Ví dụ 2. 12. . Phải có 512 MB bộ nhớ, được biểu thị bằng byte. Sao chép. Đã sao chép. . Phải được đính kèm với cụm Mặc định và do đó là Trung tâm dữ liệu mặc định. Sao chép. Đã sao chép. . Phải dựa trên mẫu Trống mặc định. Sao chép. Đã sao chép. . Phải khởi động từ ổ đĩa cứng ảo. Sao chép Máy ảo Python được viết bằng gì?Trình thông dịch Python có tên là “CPython” và được viết bằng ngôn ngữ lập trình C . Đây là triển khai mặc định cho Python. |