2009-08-10 25 views
5

Tôi đã tự hỏi làm thế nào scanf()/printf() thực sự hoạt động ở cấp độ phần cứng và hệ điều hành. Dòng dữ liệu và hệ điều hành chính xác đang làm gì vào khoảng thời gian này? Hệ điều hành thực hiện cuộc gọi nào? Và cứ như vậy ...Scanf() hoạt động bên trong hệ điều hành như thế nào?

+2

Bạn đang nói về hệ điều hành nào? –

+0

Cần thêm thông tin, – rahul

+0

Tôi không xem xét bất kỳ hệ điều hành cụ thể nào. Linux/Unix loại sẽ được tốt. Tôi chỉ muốn có một sự hiểu biết cơ bản về tình hình. – jetru

Trả lời

20

scanf() và printf() là các hàm trong libc (thư viện chuẩn C), và chúng gọi là syscalls hệ điều hành read() và write() tương ứng, nói chuyện với các mô tả tập tin stdin và stdout tương ứng (fscanf và fprintf cho phép bạn chỉ định luồng tệp bạn muốn đọc/ghi từ).

Cuộc gọi để đọc() và write() (và tất cả các syscalls) dẫn đến 'chuyển ngữ cảnh' ra khỏi ứng dụng cấp người dùng của bạn sang chế độ hạt nhân, có nghĩa là nó có thể thực hiện các thao tác đặc quyền, chẳng hạn như nói trực tiếp với phần cứng . Tùy thuộc vào cách bạn bắt đầu ứng dụng, các bộ mô tả tệp 'stdin' và 'stdout' có thể bị ràng buộc với một thiết bị bàn điều khiển (như tty0) hoặc một số loại thiết bị điều khiển ảo (như được hiển thị bởi xterm). read() và write() sao chép một cách an toàn dữ liệu vào/từ một bộ đệm hạt nhân được gọi là 'uio'.

Phần chuyển đổi chuỗi định dạng của scanf và printf không xuất hiện ở chế độ hạt nhân, nhưng chỉ trong chế độ người dùng thông thường (bên trong 'libc'), quy tắc chung của ngón tay cái với syscalls là bạn chuyển sang chế độ hạt nhân không thường xuyên có thể, cả hai để tránh chi phí hoạt động của bối cảnh chuyển đổi, và cho an ninh (bạn cần phải rất cẩn thận về bất cứ điều gì xảy ra trong chế độ hạt nhân! ít mã trong chế độ hạt nhân có nghĩa là ít lỗi/lỗ hổng bảo mật trong hệ điều hành).

btw .. tất cả điều này được viết từ phối cảnh unix, tôi không biết cách MS Windows hoạt động.

+0

Chuyển ngữ cảnh âm thanh chậm nếu nó đọc từng byte riêng lẻ. Tất nhiên, nó không thực sự quan trọng trong ngày và tuổi tác, nhưng tôi chỉ muốn biết liệu tôi có đúng trong sự hiểu biết này không. –

+1

Các syscalls đọc và ghi có một số byte để truyền qua UIO dưới dạng tham số, vì vậy nó không phải tạo một syscall riêng biệt cho từng byte đơn. Bạn cũng sẽ nghĩ rằng đối với các hàm đầu vào đơn giản như getchar() thì phải có một cuộc gọi riêng biệt cho mỗi ký tự, nhưng thực tế những ngày này libc là một chút thông minh hơn và nó giữ một bộ đệm (bên trong libc). Vì vậy, nó có thể tránh được chi phí hiệu suất của bối cảnh chuyển đổi rất nhiều bằng cách điền vào bộ đệm của nó, sau đó xử lý một chút của mỗi lần bạn getchar() hoặc scanf(), cho đến khi bộ đệm trống, và chỉ sau đó thực hiện một syscall. –

+0

Về chủ đề "nó không thực sự quan trọng trong ngày này một tuổi", trong thực tế, bạn sẽ ngạc nhiên làm thế nào đáng kể làm cho syscalls tất cả các thời gian sẽ ảnh hưởng đến hiệu suất. Hãy xem xét rằng syscalls là * ít nhất * 10 lần chậm như một cuộc gọi chức năng thường xuyên. Ví dụ: nếu bạn có bộ đệm có kích thước 1024 byte, bạn chỉ đang tạo 1/1024 làm nhiều syscalls.Viết một thực hiện C của lệnh 'cp' có và không có một bộ đệm là một ví dụ tuyệt vời, tôi sẽ đăng nó trong một vài phút. –

0

Tôi nghĩ rằng hệ điều hành chỉ cung cấp hai luồng, một cho đầu vào và đầu kia cho đầu ra, luồng trừu tượng ra cách dữ liệu đầu ra được hiển thị hoặc dữ liệu đầu vào đến từ đâu.

vì vậy những gì scanf & printf đang làm chỉ là thêm byte (hoặc tiêu thụ byte) từ một trong hai luồng.

+0

Đây là mức trừu tượng cao. Tôi muốn biết chi tiết về cách các luồng này hoạt động với phần cứng và cách hệ điều hành quản lý tất cả dữ liệu. – jetru

1

Trên hệ điều hành của tôi, tôi đang làm việc với scanf và printf dựa trên hàm getch() ant putch().

+0

Wow đó là một cái gì đó. Tôi đã quản lý để thay đổi đầu ra từ uart sang TCP/IP khi có một máy khách kết nối. Đó là vi hạt nhân hợp tác không được ưu tiên đơn giản cho hệ thống nhúng. –

Các vấn đề liên quan