2009-03-29 10 views
5

Nếu tôi đếm trên hệ thống write() gọi để viết ví dụ, 100 byte, tôi luôn đặt lệnh write() đó vào một vòng lặp để kiểm tra xem độ dài được trả lại có phải là thứ tôi mong muốn gửi hay không, nếu không, nó bumps con trỏ đệm và giảm độ dài bằng số tiền đã được viết. Vì vậy, một lần nữa tôi chỉ làm điều này, nhưng bây giờ có StackOverflow, tôi có thể hỏi tất cả các bạn nếu mọi người biết khi nào viết của tôi sẽ viết TẤT CẢ mà tôi yêu cầu so với trả lại một phần viết?Khi nào thì hệ thống write() gọi ghi tất cả các bộ đệm được yêu cầu so với việc viết một phần?

Nhận xét bổ sung: Trả lời của X-Istence nhắc tôi rằng tôi nên lưu ý rằng bộ mô tả tệp đã chặn (tức là không chặn). Tôi nghĩ rằng anh ta gợi ý rằng cách duy nhất một write() trên một mô tả tập tin chặn sẽ không viết tất cả các dữ liệu được chỉ định là khi write() bị gián đoạn bởi một tín hiệu. Điều này dường như làm cho cảm giác ít nhất là trực quan đối với tôi ...

Trả lời

3

Bạn cần phải kiểm tra errno để xem cuộc gọi của bạn có bị gián đoạn hay không hoặc tại sao write() trả lại sớm và tại sao nó chỉ ghi một số byte nhất định.

Từ man 2 write

Khi sử dụng non-blocking I/O trên các đối tượng như ổ cắm mà phải tuân theo điều khiển luồng, viết() và writev() có thể viết byte ít hơn yêu cầu; giá trị trả về phải được ghi lại và phần còn lại của hoạt động sẽ được thử lại khi có thể.

Về cơ bản, trừ khi bạn đang ghi vào một ổ cắm không chặn, thời gian khác duy nhất điều này sẽ xảy ra là nếu bạn bị gián đoạn bởi tín hiệu.

[EINTR] Tín hiệu bị gián đoạn ghi trước khi hoàn thành.

Xem phần Lỗi trong số man page để biết thêm thông tin về những gì có thể được trả lại và thời điểm sẽ được trả lại. Từ đó bạn cần phải tìm ra nếu lỗi là đủ nghiêm trọng để đăng nhập một lỗi và bỏ thuốc lá, hoặc nếu bạn có thể tiếp tục hoạt động trong tầm tay!

Tất cả điều này được thảo luận trong sách: Advanced Unix Programming by Marc J. Rochkind, tôi đã viết vô số chương trình với sự trợ giúp của cuốn sách này và sẽ đề xuất trong khi lập trình cho hệ điều hành giống UNIX.

+0

Để rõ ràng, trên Linux, 'errno' là _not_ được đặt khi viết ghi một số số khác không phải là byte, ngay cả khi nhỏ hơn số tiền được yêu cầu. Nó được _only_ đặt khi 0 byte được ghi. Vì vậy, nói chung bạn không thể tìm ra lý do tại sao một ghi là _partial_, nhưng nếu tình hình là dai dẳng (ví dụ, đĩa là đầy đủ), bạn sẽ tìm hiểu trên ** ** viết tiếp theo, mà sẽ thất bại với giá trị trả về '- 1' và đặt 'errno'. Đây là một [chủ đề cổ điển] (http://yarchive.net/comp/linux/partial_reads_writes.html) về lý do tại sao điều này là như vậy. – BeeOnRope

-1

Ghi không nên có bất kỳ lý do nào để viết một phần bộ đệm afaik. Lý do tôi có thể nghĩ đến cho việc viết một phần là nếu bạn hết dung lượng ổ đĩa, bạn đang viết quá trình kết thúc thiết bị chặn hoặc nếu bạn đang viết thư cho thiết bị char/một số loại thiết bị khác.

Tuy nhiên, kế hoạch để thử lại viết một cách mù quáng có lẽ không phải là tốt như vậy - kiểm tra errno để xem liệu bạn có nên thử lại trước không.

+0

Bạn không thể dựa vào errnon vì nó không phải là lỗi, câu trả lời Artyom là cách để đi. Đưa ra lời khuyên cho trường hợp thông thường chỉ là sai, thiết bị char, fifo, socket etc ... không phải là quá bất thường anyway, và bạn không biết ở đâu hoặc khi nào mã sẽ được tái sử dụng. – shodanex

+0

Đó là chính xác những gì tôi đã nói - kiểm tra errno để xem liệu bạn có nên thử lại –

+0

Nhưng viết một phần không phải là lỗi do đó không có gì để kiểm tra – shodanex

5

ghi có thể trả lại một phần ghi, đặc biệt là sử dụng các thao tác trên ổ cắm hoặc nếu bộ đệm trong đầy. Vì vậy, cách tốt nhất là làm như sau:

while(size > 0 && (res=write(fd,buff,size))!=size) { 
    if(res<0 && errno==EINTR) 
     continue; 
    if(res < 0) { 
     // real error processing 
     break; 
    } 
    size-=res; 
    buf+=res; 
} 

Không bao giờ chuyển tiếp vào những gì thường xảy ra ...

Lưu ý: trong trường hợp đĩa đầy đủ, bạn sẽ nhận được ENOSPC không phần ghi.

+1

Mã của bạn đọc một phần: 'size = -res;'. Không nên là: 'size- = res;'? – Urhixidur

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