2012-01-23 50 views
14

Hãy xem xét các dòng mã sau đây:read() từ stdin

while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0) 

Theo hiểu biết của tôi read/write chức năng là một phần của phi đệm I/O. Vậy điều đó có nghĩa là hàm read() sẽ chỉ đọc một ký tự cho mỗi cuộc gọi từ stdio? Hay nói cách khác, giá trị của n sẽ

-1 in case of error 
n = 0 in case of EOF 
    1 otherwise 

Nếu nó không phải là trường hợp, khi nào các read() chức năng trên sẽ quay trở lại và tại sao?

Lưu ý: Tôi cũng nghĩ rằng read() sẽ đợi cho đến khi nó đọc thành công BUFSIZ số ký tự từ stdin. Nhưng điều gì xảy ra trong một số trường hợp các ký tự có sẵn để đọc ít hơn BUFSIZ? Sẽ đọc chờ đợi mãi mãi hoặc cho đến khi EOF đến (Ctrl + D trên unix hoặc Ctrl + Z trên cửa sổ)?

Ngoài ra, hãy nói BUFSIZ = 100stdin = ACtrl+D (tức là EOF ngay sau một ký tự đơn). Bây giờ số lần while loop sẽ lặp lại như thế nào?

+2

Là một FYI, tôi tin rằng bạn có thể đọc từ '0', là đầu vào tiêu chuẩn, nhưng chỉ có thể sử dụng 'stdin' với' fread() '. –

+0

yeah u r right ... thnx !! Vì stdin thuộc loại 'FILE *', nó không thể được sử dụng với 'read' –

+3

hoặc' STDIN_FILENO' nếu bạn đang trong tâm trạng ghi nhãn. – Dave

Trả lời

2

Khi read() bang manpage:

Return Value

Mở thành công, số byte đọc được trả lại (không chỉ kết thúc tập tin), và vị trí tập tin được tiến của thành viên này con số. Nó không phải là một lỗi nếu số này nhỏ hơn số byte yêu cầu; điều này có thể xảy ra, ví dụ vì ít byte thực sự có sẵn ngay bây giờ (có thể vì chúng tôi đã gần cuối tập tin hoặc vì chúng tôi đang đọc từ một đường ống hoặc từ thiết bị đầu cuối) hoặc vì read() bị gián đoạn bởi tín hiệu. Khi lỗi, -1 được trả về và errno được đặt một cách thích hợp. Trong trường hợp này, nó không được chỉ định cho dù vị trí tệp (nếu có) có thay đổi hay không.

Vì vậy, mỗi read() sẽ đọc lên đến số byte nhất định; nhưng nó có thể đọc ít hơn. "Không đệm" có nghĩa là nếu bạn chỉ định read(fd, bar, 1), đọc sẽ chỉ đọc một byte. Buffered IO cố gắng đọc trong quanta của BUFSIZ, ngay cả khi bạn chỉ muốn một ký tự. Điều này nghe có vẻ lãng phí, nhưng nó tránh được phí tổn của việc thực hiện các cuộc gọi hệ thống, điều này làm cho nó nhanh chóng.

+0

bạn trả lời là quá chung chung ... vui lòng cụ thể hơn cho vấn đề –

0
  1. đọc các nỗ lực để nhận tất cả các ký tự được yêu cầu.
  2. nếu EOF xảy ra trước khi tất cả các ký tự được yêu cầu có thể được trả về, nó sẽ trả lại số tiền đã nhận sau khi thực hiện điều này lần đọc tiếp theo trả về -1, để cho bạn biết kết thúc tệp.

Điều gì sẽ xảy ra khi nó cố đọc và không có gì liên quan đến việc chặn. Bạn có thể gọi mở để đọc một tập tin chặn hoặc không chặn. "chặn" có nghĩa là đợi cho đến khi có thứ gì đó trở lại.

Đây là những gì bạn thấy trong trình bao đang chờ nhập. Nó ngồi đó. Cho đến khi bạn nhấn trở lại.

Không chặn nghĩa là đọc sẽ trả về không có byte dữ liệu nếu không có.Tùy thuộc vào rất nhiều yếu tố khác mà sẽ làm cho một câu trả lời hoàn toàn chính xác không sử dụng được cho bạn, đọc sẽ thiết lập errno đến một cái gì đó như EWOULDBLOCK, cho phép bạn biết lý do tại sao đọc của bạn trả lại không byte. Nó không nhất thiết phải là một lỗi nghiêm trọng.

Mã của bạn có thể kiểm tra trừ để tìm EOF hoặc lỗi

17

Cách đọc() hoạt động phụ thuộc vào nội dung đang được đọc. Đối với các tệp thông thường, nếu bạn yêu cầu ký tự N, bạn nhận được N ký tự nếu chúng có sẵn, nhỏ hơn N nếu kết thúc tệp can thiệp.

Nếu read() đang đọc từ thiết bị đầu cuối ở chế độ chuẩn/nấu, trình điều khiển tty cung cấp dữ liệu một dòng tại một thời điểm. Vì vậy, nếu bạn yêu cầu read() nhận được 3 ký tự hoặc 300, đọc sẽ treo cho đến khi trình điều khiển tty đã thấy một dòng mới hoặc khóa EOF đã xác định của thiết bị đầu cuối, và sau đó read() sẽ trả về với số ký tự trong dòng hoặc số ký tự bạn đã yêu cầu, tùy theo số nào nhỏ hơn.

Nếu read() đang đọc từ thiết bị đầu cuối ở chế độ không chuẩn/thô, đọc sẽ có quyền truy cập vào các lần nhấn phím ngay lập tức. Nếu bạn yêu cầu read() lấy 3 ký tự, nó có thể trở lại với bất cứ nơi nào từ 0 đến 3 ký tự tùy thuộc vào thời gian đầu vào và cách thiết bị đầu cuối được cấu hình.

read() sẽ hoạt động khác khi đối mặt với tín hiệu, trả lại ít hơn số ký tự yêu cầu hoặc -1 với errno được đặt thành EINTR nếu tín hiệu bị gián đoạn đọc trước khi bất kỳ ký tự nào đến.

read() sẽ hoạt động khác nếu trình mô tả đã được định cấu hình cho I/O không chặn. read() sẽ trả về -1 với errno được đặt thành EAGAIN hoặc EWOULDBLOCK nếu không có đầu vào nào có sẵn ngay lập tức. Điều này áp dụng cho ổ cắm.

Vì vậy, như bạn có thể thấy, bạn sẽ sẵn sàng cho những điều bất ngờ khi bạn gọi read(). Bạn sẽ không luôn nhận được số lượng ký tự mà bạn yêu cầu và bạn có thể gặp phải các lỗi không nghiêm trọng như EINTR, có nghĩa là bạn nên thử lại hàm read().

+0

ohh ... thực sự tôi bỏ lỡ gõ dấu ngoặc đơn ... thnx !! –

+0

bây giờ trở lại vấn đề thực tế. –

3

Mã của bạn đọc:

while((n = read(0, buff, BUFSIZ) != 0)) 

Đây là sai lầm - các dấu ngoặc đơn có nghĩa là nó được hiểu là:

while ((n = (read(0, buff, BUFSIZ) != 0)) != 0) 

nơi điều kiện boolean được đánh giá trước khi chuyển nhượng, nên n sẽ chỉ có được giá trị 0 (điều kiện không đúng) và 1 (điều kiện là đúng).

Bạn nên viết:

while ((n = read(0, buff, BUFSIZ)) > 0) 

này dừng trên EOF hoặc một lỗi đọc, và n cho phép bạn biết được tình trạng bạn gặp phải.


Rõ ràng, mã ở trên là lỗi đánh máy trong câu hỏi.

I/O chưa được lọc sẽ đọc lên số ký tự bạn đã đọc (nhưng không nhiều hơn). Nó có thể đọc ít hơn trên tài khoản của EOF hoặc một lỗi. Nó cũng có thể đọc ít hơn bởi vì ít có sẵn tại thời điểm cuộc gọi. Xem xét một thiết bị đầu cuối; thông thường, điều đó sẽ chỉ đọc đến cuối dòng vì không có sẵn nhiều hơn thế nữa. Hãy xem xét một đường ống; nếu quá trình cho ăn đã tạo ra 128 byte chưa đọc, sau đó nếu BUFSIZ là 4096, bạn sẽ chỉ nhận được 128 byte từ đọc.Trình mô tả tệp không chặn có thể trả về vì không có gì; một ổ cắm có thể trả lại ít byte hơn vì chưa có thêm thông tin; một đĩa đọc có thể trả lại ít byte hơn vì có ít hơn số byte được yêu cầu còn lại trong tệp khi đọc được thực hiện.

Nói chung, mặc dù, read() sẽ không trả lại chỉ một byte nếu bạn yêu cầu nhiều byte.

+0

đó là một lỗi đánh máy ... tôi đã sửa nó ... bây giờ trở lại vấn đề thực tế. –

0

Khi chúng tôi nói read không bị chặn, điều đó có nghĩa là không có bộ đệm diễn ra ở cấp quy trình của bạn sau khi dữ liệu được kéo ra khỏi mô tả tệp mở cơ bản, là tài nguyên có khả năng chia sẻ. Nếu stdin là thiết bị đầu cuối, có thể có ít nhất 2 bộ đệm bổ sung đang phát, tuy nhiên:

  1. Bộ đệm đầu cuối có thể chứa 1-4k dữ liệu ngoài dòng cho đến.
  2. Bộ đệm chế độ nấu/chuẩn của hạt nhân để nhập/chỉnh sửa dòng trên thiết bị đầu cuối, cho phép người dùng thực hiện chỉnh sửa nguyên thủy (backspace, backword, erase line, vv) trên dòng cho đến khi được gửi (đến bộ đệm được mô tả ở trên) bằng cách nhấn enter.

read sẽ rút bất kỳ nội dung nào đã được gửi, tối đa độ dài đọc tối đa mà bạn đã chuyển đến, nhưng không thể kéo bất kỳ thứ gì từ bộ đệm chỉnh sửa đường. Nếu bạn muốn tắt lớp đệm bổ sung này, bạn cần tra cứu cách tắt chế độ đã nấu/chuẩn cho thiết bị đầu cuối bằng cách sử dụng tcsetattr, v.v.