Các kênh I / O được triển khai trong nhân Linux như thế nào?


8

stdin, stdout, stderr là một số số nguyên lập chỉ mục thành cấu trúc dữ liệu 'biết' các kênh I / O nào sẽ được sử dụng cho quy trình. Tôi hiểu cấu trúc dữ liệu này là duy nhất cho mọi quy trình. Các kênh I / O không có gì ngoài một số cấu trúc mảng dữ liệu có cấp phát bộ nhớ động?


bởi các kênh I / O, ý bạn là các luồng hoặc đường ống? Ngoài ra, điều này có thể thay đổi theo hạt nhân. có lẽ bạn sẽ cần phải hỏi về một hạt nhân cụ thể.
strugee

1
@strugee Mình đang nói về kernel Linux. Tôi có nghĩa là luồng theo kênh I / O. Làm thế nào những luồng này được thực hiện trong linux? một số mảng hoặc một cái gì đó?
KawaiKx

Câu trả lời:


14

Trong Unix như hệ điều hành, đầu vào, đầu ra và báo lỗi dòng tiêu chuẩn được xác định bởi các file descriptor 0, 1, 2. Trên Linux, chúng được hiển thị dưới prochệ thống tập tin trong /proc/[pid]/fs/{0,1,2}. Những tập tin này thực sự là các liên kết tượng trưng cho một pseudoterminal thiết bị theo các /dev/ptsthư mục.

Pseudoterminal (PTY) là một cặp thiết bị ảo, một chủ giả giả (PTM) và một nô lệ giả da (PTS) (gọi chung là cặp giả ngẫu nhiên ), cung cấp một kênh IPC, giống như một ống hai chiều được kết nối với thiết bị đầu cuối và chương trình trình điều khiển sử dụng mã giả để gửi đầu vào và nhận đầu vào từ chương trình cũ.

Một điểm quan trọng là nô lệ giả xuất hiện giống như một thiết bị đầu cuối thông thường, ví dụ: nó có thể được chuyển đổi giữa chế độ phi núi và chính tắc (mặc định), trong đó nó diễn giải một số ký tự đầu vào, như tạo SIGINTtín hiệu khi một ký tự ngắt (thường được tạo bằng cách nhấn Ctrl+ Ctrên bàn phím) được ghi vào bản gốc giả hoặc khiến phần tiếp theo read()quay trở lại 0khi gặp ký tự cuối tệp (thường được tạo bởi Ctrl+ D). Các hoạt động khác được hỗ trợ bởi các thiết bị đầu cuối đang bật hoặc tắt tiếng vang, thiết lập nhóm quy trình tiền cảnh, v.v.

Giả hành có một số cách sử dụng:

  • Chúng cho phép các chương trình muốn sshvận hành các chương trình định hướng đầu cuối trên một máy chủ khác được kết nối qua mạng. Một chương trình định hướng thiết bị đầu cuối có thể là bất kỳ chương trình nào, thường sẽ được chạy trong phiên thiết bị đầu cuối tương tác. Đầu vào, đầu ra và lỗi tiêu chuẩn của một chương trình như vậy không thể được kết nối trực tiếp với ổ cắm, vì các ổ cắm không hỗ trợ các chức năng liên quan đến thiết bị đầu cuối nói trên.

  • Chúng cho phép các chương trình muốn expectlái một chương trình định hướng đầu cuối tương tác từ một tập lệnh.

  • Chúng được sử dụng bởi các trình giả lập thiết bị đầu cuối như xtermđể cung cấp chức năng liên quan đến thiết bị đầu cuối.

  • Chúng được sử dụng bởi các chương trình như screenghép kênh một thiết bị đầu cuối vật lý duy nhất giữa nhiều quy trình.

  • Chúng được sử dụng bởi các chương trình như scriptđể ghi lại tất cả đầu vào và đầu ra xảy ra trong một phiên shell.

Các PTY kiểu Unix98 , được sử dụng trong Linux, được thiết lập như sau:

  • Chương trình trình điều khiển mở bộ ghép kênh chính giả thiết bị đầu cuối tại dev/ptmx, tại đó nó nhận được một mô tả tệp aa cho PTM, và một thiết bị PTS được tạo trong /dev/ptsthư mục. Mỗi mô tả tệp thu được bằng cách mở /dev/ptmxlà một PTM độc lập với PTS được liên kết riêng.

  • Các chương trình điều khiển gọi fork()để tạo một tiến trình con, lần lượt thực hiện các bước sau:

    • Đứa trẻ gọi setsid()để bắt đầu một phiên mới, trong đó đứa trẻ là người lãnh đạo phiên. Điều này cũng khiến đứa trẻ mất thiết bị đầu cuối kiểm soát của nó .

    • Đứa trẻ tiến hành mở thiết bị PTS tương ứng với PTM được tạo bởi chương trình trình điều khiển. Vì đứa trẻ là người lãnh đạo phiên, nhưng không có thiết bị đầu cuối kiểm soát, PTS trở thành thiết bị đầu cuối kiểm soát trẻ em.

    • Đứa trẻ sử dụng dup()để sao chép bộ mô tả tệp cho thiết bị nô lệ trên đầu vào, đầu ra và lỗi tiêu chuẩn.

    • Cuối cùng, đứa trẻ gọi exec()để bắt đầu chương trình định hướng thiết bị đầu cuối được kết nối với thiết bị giả.

Tại thời điểm này, bất cứ điều gì chương trình trình điều khiển ghi vào PTM, sẽ xuất hiện dưới dạng đầu vào cho chương trình định hướng đầu cuối trên PTS và ngược lại.

Khi hoạt động ở chế độ chính tắc, đầu vào của PTS được đệm theo từng dòng. Nói cách khác, giống như với các thiết bị đầu cuối thông thường, chương trình đọc từ PTS chỉ nhận được một dòng đầu vào khi một ký tự dòng mới được ghi vào PTM. Khi hết dung lượng bộ đệm, write()khối cuộc gọi tiếp tục cho đến khi một số đầu vào đã được sử dụng.

Trong hạt nhân Linux, các tập tin liên quan đến các cuộc gọi hệ thống open(), read(), write() stat()vv được thực hiện trong hệ thống tập tin (VFS) lớp ảo, cung cấp một giao diện hệ thống tập tin thống nhất cho các chương trình không gian người dùng. VFS cho phép các cài đặt hệ thống tệp khác nhau cùng tồn tại trong nhân. Khi các chương trình không gian người dùng gọi các cuộc gọi hệ thống đã nói ở trên, VFS sẽ chuyển hướng cuộc gọi đến việc thực hiện hệ thống tệp thích hợp.

Các thiết bị PTS bên dưới /dev/ptsđược quản lý bởi việc devptstriển khai hệ thống tệp được xác định trong /fs/devpts/inode.c, trong khi trình điều khiển TTY cung cấp ptmxthiết bị kiểu Unix98 được xác định trong drivers/tty/pty.c.

Việc đệm giữa các thiết bị TTY và các quy tắc dòng TTY , chẳng hạn như giả, được cung cấp cấu trúc bộ đệm được duy trì cho mỗi thiết bị tty, được xác định tronginclude/linux/tty.h

Trước phiên bản kernel 3.7, bộ đệm là bộ đệm lật :

#define TTY_FLIPBUF_SIZE 512

struct tty_flip_buffer {
        struct tq_struct tqueue;
        struct semaphore pty_sem;
        char             *char_buf_ptr;
        unsigned char    *flag_buf_ptr;
        int              count;
        int              buf_num;
        unsigned char    char_buf[2*TTY_FLIPBUF_SIZE];
        char             flag_buf[2*TTY_FLIPBUF_SIZE];
        unsigned char    slop[4];
};

Cấu trúc chứa lưu trữ được chia thành hai bộ đệm kích thước bằng nhau. Các bộ đệm được đánh số 0(nửa đầu char_buf/flag_buf) và 1(nửa sau). Trình điều khiển lưu dữ liệu vào bộ đệm được xác định bởi buf_num. Các bộ đệm khác có thể được tuôn ra theo kỷ luật dòng.

Bộ đệm đã được 'lật' bằng cách chuyển đổi buf_numgiữa 01. Khi được buf_numthay đổi char_buf_ptrflag_buf_ptr được đặt thành phần đầu của bộ đệm được xác định bởi buf_numcountđược đặt thành 0.

Kể từ phiên bản kernel 3.7, bộ đệm lật TTY đã được thay thế bằng các đối tượng được phân bổ thông qua kmalloc()tổ chức theo vòng . Trong một tình huống bình thường đối với một cổng nối tiếp điều khiển IRQ ở tốc độ điển hình, hành vi của chúng khá giống với bộ đệm lật cũ; hai bộ đệm cuối cùng được phân bổ và các chu kỳ kernel giữa chúng như trước đây. Tuy nhiên, khi có độ trễ hoặc tốc độ tăng, việc thực hiện bộ đệm mới hoạt động tốt hơn vì vùng đệm có thể tăng lên một chút.


Câu trả lời là có kiến ​​thức vì điều này là vô cùng khó để đi qua.
étale-cohomology

-1

Từ các trang man cho bất kỳ một trong ba trang, nó giải thích câu trả lời:

   Under  normal circumstances every UNIX program has three streams opened
   for it when it starts up, one for input, one for output,  and  one  for
   printing diagnostic or error messages.  These are typically attached to
   the user's terminal but might instead  refer  to  files  or
   other  devices,  depending  on what the parent process chose to set up.

   The input stream is referred to as "standard input"; the output  stream
   is  referred  to as "standard output"; and the error stream is referred
   to as "standard error".  These terms are abbreviated to form  the  sym-
   bols used to refer to these files, namely stdin, stdout, and stderr.

   Each  of these symbols is a stdio(3) macro of type pointer to FILE, and
   can be used with functions like fprintf(3) or fread(3).

   Since FILEs are a buffering wrapper around UNIX file  descriptors,  the
   same  underlying  files  may  also  be accessed using the raw UNIX file
   interface, that is, the functions like read(2) and lseek(2).

   On program startup, the integer file descriptors  associated  with  the
   streams  stdin,  stdout, and stderr are 0, 1, and 2, respectively.  The
   preprocessor symbols STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO are
   defined  with  these values in <unistd.h>.

Câu trả lời này mô tả việc thực hiện stdin, stdoutstderrtừ quan điểm của thư viện C, nhưng câu hỏi là một cách rõ ràng về việc thực hiện kernel. Tôi đã cố gắng giải thích cho quan điểm hạt nhân trong câu trả lời của tôi .
Thomas Nyman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.