2013-02-08 12 views
6

Tôi đang phát trực tuyến tệp lớn (1Gb) qua HTTP tới máy chủ của tôi bằng Qt trên thiết bị Linux bị hạn chế về bộ nhớ. Khi tôi lần đầu tiên nhận được tiêu đề, tôi xác định nơi để ghi dữ liệu trên hệ thống tập tin, tạo một con trỏ QFile đến vị trí đó và mở tệp để thêm vào. Có một chức năng 'tích lũy' trong máy chủ được gọi là mỗi lần dữ liệu mới đến ổ cắm. Từ hàm tích lũy đó, tôi muốn truyền dữ liệu trực tiếp đến tệp thông qua write(). Bạn có thể thấy chức năng tích lũy của tôi bên dưới.Qt Truyền tệp lớn qua HTTP và Flushing sang eMMC Flash

Vấn đề của tôi là sử dụng bộ nhớ khi thực hiện việc này - Tôi hết bộ nhớ. Không nên tôi có thể tuôn ra() và fsync() mỗi lần lặp lại của sự tích lũy và không phải lo lắng về việc sử dụng RAM? Tôi đang làm gì sai và làm thế nào tôi có thể sửa lỗi này? Cảm ơn -

tôi mở tập tin của tôi một lần trước khi chức năng tích lũy:

// Open the file 
filePointerToWriteTo->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered) 

Đây là một phần của chức năng tích lũy:

// Extract the QFile pointer from the QVariant 
QFile *filePointerToWriteTo = (QFile *)(containerForPointer->pointer).value<void *>(); 

qDebug() << "APPENDING bytes: " << data.length(); 

// Write to the file and sync 
filePointerToWriteTo->write(data); 
filePointerToWriteTo->waitForBytesWritten(-1); 
filePointerToWriteTo->flush(); // Flush 
fsync(filePointerToWriteTo->handle()); // Make sure bytes are written to disk 

EDIT:

tôi instrumented mã của tôi và cuộc gọi 'waitForBytesWritten (-1)' gọi ALWAYS trả về 'false'. Các tài liệu nói điều này sẽ đợi cho đến khi dữ liệu được ghi vào thiết bị.

Ngoài ra, nếu tôi chỉ ghi chú dòng 'ghi (dữ liệu)', thì bộ nhớ miễn phí của tôi sẽ không bao giờ giảm. Điều gì có thể xảy ra? Làm thế nào để 'viết' tiêu thụ quá nhiều bộ nhớ?

EDIT:

Bây giờ tôi làm như sau. Tôi không hết bộ nhớ, nhưng bộ nhớ miễn phí của tôi giảm xuống còn 2Mb và di chuyển đến đó cho đến khi toàn bộ tệp được chuyển. Tại thời điểm đó, bộ nhớ được giải phóng. Nếu tôi giết chuyển ở giữa, hạt nhân dường như giữ lại bộ nhớ vì nó vẫn còn khoảng 2Mb miễn phí cho đến khi tôi khởi động lại quá trình và cố gắng ghi vào cùng một tệp. Tôi vẫn nghĩ rằng tôi sẽ có thể sử dụng và xối vào bộ nhớ mỗi lần lặp:

// Extract the QFile pointer from the QVariant 
QFile *filePointerToWriteTo = (QFile *)(containerForPointer->pointer).value<void *>(); 

int numberOfBytesWritten = filePointerToWriteTo->write(data); 
qDebug() << "APPENDING bytes: " << data.length() << " ACTUALLY WROTE: " << numberOfBytesWritten; 

// Flush and sync 
bool didWaitForWrite = filePointerToWriteTo->waitForBytesWritten(-1); // <----------------------- This ALWAYS returns false! 
filePointerToWriteTo->flush(); // Flush 
fsync(filePointerToWriteTo->handle()); // Make sure bytes are written to disk 
fdatasync(filePointerToWriteTo->handle()); // Specific Sync 
sync(); // Total sync 

EDIT:

Đây là loại âm thanh như tôi hiểu lầm Linux bộ nhớ đệm. Sau khi đọc bài đăng này ->http://blog.scoutapp.com/articles/2010/10/06/determining-free-memory-on-linux, có thể tôi hiểu nhầm đầu ra của 'mt miễn phí'. Tôi đã xem lĩnh vực 'miễn phí' trong đầu ra đó và thấy nó thả để di chuột khoảng 2MB khi chuyển tập tin lớn. Tôi chỉ muốn thấy nó trở lại mức độ cao của dữ liệu miễn phí khi chuyển tập tin được thực hiện.

+0

Môi trường này đang chạy ở đâu? Đây có phải là ứng dụng cgi không? – Jay

+0

Qt được nhúng trong môi trường Embedded Linux. Máy chủ hoàn toàn nằm trong Qt/C++ và nghe trên cổng 80. – PhilBot

+0

Phiên bản Qt nào? Kiểm tra giá trị trả về của write/waitForBytesWritten/flush (và cũng mở, nhưng điều đó không liên quan). –

Trả lời

1

Tôi nghĩ rằng Linux chỉ là bộ nhớ đệm mọi thứ có thể và giải phóng những gì nó có thể rảnh rỗi xung quanh giới hạn bộ nhớ miễn phí 2MB. Tôi không hết bộ nhớ khi nhận hoặc gửi ~ 2Gb tệp trên hệ thống RAM 512 MB. Trong chương trình Qt của tôi, sau khi nhận được tất cả dữ liệu, hãy thêm vào tệp và đóng tệp. Tôi làm như sau trong QProcess để xem bộ nhớ 'miễn phí' của tôi trở lại trong lệnh 'free -mt' trong một thiết bị đầu cuối riêng biệt:

// Now we've returned a large file - so free up cache in linux 
QProcess freeCachedMemory; 
freeCachedMemory.start("sh"); 
freeCachedMemory.write("sync; echo 3 > /proc/sys/vm/drop_caches"); // Sync to disk and clear Linux cache 
freeCachedMemory.waitForFinished(); 
freeCachedMemory.close(); 
+0

Gặp phải vấn đề tương tự ...Trong trường hợp của chúng tôi, ứng dụng của chúng tôi bị treo bởi hệ điều hành (và không đáp ứng) trong một thời gian khi RAM được đầy đủ với răng giả và inodes (tôi giả sử cho đến khi hệ điều hành tuôn ra dữ liệu được lưu vào đĩa). Chỉ cần fyi, 'sync && sysctl -w vm.drop_caches = 2' cũng có thể được sử dụng. – mBardos