ถ้าความเร็วเป็นสิ่งที่สำคัญและการบีบอัดไม่จำเป็นต้องคุณสามารถขอห่อ syscall ที่ใช้โดยtarใช้LD_PRELOADการเปลี่ยนแปลงtarในการคำนวณนั้นเรา โดย reimplementing ไม่กี่ของฟังก์ชั่นเหล่านี้เพื่อให้เหมาะกับความต้องการของเรา (คำนวณขนาดของข้อมูลการส่งออกที่มีศักยภาพ tar) เราสามารถกำจัดจำนวนมากreadและการที่จะดำเนินการในการดำเนินงานตามปกติของwrite tarสิ่งนี้ทำให้tarเร็วขึ้นมากเนื่องจากไม่จำเป็นต้องสลับบริบทไปมาในเคอร์เนลที่ใดก็ตามที่อยู่ใกล้มากและมีเพียงstatไฟล์ / โฟลเดอร์ที่ร้องขอเท่านั้นที่จำเป็นต้องอ่านจากดิสก์แทนที่จะเป็นข้อมูลไฟล์จริง
โค้ดข้างล่างนี้รวมถึงการใช้งานของclose, readและwriteฟังก์ชั่น POSIX แมโครOUT_FDควบคุมไฟล์ descriptor ที่เราคาดว่าtarจะใช้เป็นไฟล์เอาต์พุต ขณะนี้มันถูกตั้งค่าเป็น stdout
readเปลี่ยนเป็นเพียงคืนค่าความสำเร็จของcountไบต์แทนการเติม buf ด้วยข้อมูลเนื่องจากข้อมูลจริงที่ไม่ได้อ่าน buf จะไม่มีข้อมูลที่ถูกต้องสำหรับการส่งผ่านไปยังการบีบอัดและดังนั้นหากการบีบอัดถูกใช้เราจะคำนวณว่าไม่ถูกต้อง ขนาด.
writeถูกเปลี่ยนเพื่อรวมcountไบต์อินพุตลงในตัวแปรโกลบอลtotalและส่งคืนค่าความสำเร็จของcountไบต์เฉพาะเมื่อไฟล์ descriptor ตรงกันOUT_FDมิฉะนั้นจะเรียก wrapper ดั้งเดิมที่ได้มาจากdlsymการดำเนินการ syscall ในชื่อเดียวกัน
closeยัง preforms ฟังก์ชั่นดั้งเดิมทั้งหมด แต่ถ้า file descriptor ตรงกับ OUT_FD จะรู้ว่าtarพยายามเขียนไฟล์ tar ดังนั้นtotalหมายเลขจึงเป็นหมายเลขสุดท้ายและพิมพ์ไปยัง stdout
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
printf("%" PRIu64 "\n", total);
}
int close(int fd)
{
if(! original_close)
{
original_close = dlsym(RTLD_NEXT, "close");
}
if(fd == OUT_FD)
{
print_total();
}
return original_close(fd);
}
ssize_t read(int fd, void *buf, size_t count)
{
return count;
}
ssize_t write(int fd, const void *buf, size_t count)
{
if(!original_write)
{
original_write = dlsym(RTLD_NEXT, "write");
}
if(fd == OUT_FD)
{
total += count;
return count;
}
return original_write(fd, buf, count);
}
การเปรียบเทียบเกณฑ์เปรียบเทียบโซลูชันที่การอ่านดิสก์การเข้าถึงและ syscalls ทั้งหมดของการดำเนินการ tar ปกติจะดำเนินการกับLD_PRELOADโซลูชัน
$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real 0m0.457s
user 0m0.064s
sys 0m0.772s
tarsize$ time ./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real 0m0.016s
user 0m0.004s
sys 0m0.008s
รหัสด้านบนสคริปต์สร้างพื้นฐานเพื่อสร้างรายการด้านบนเป็นไลบรารีที่ใช้ร่วมกันและสคริปต์ที่มี " LD_PRELOADเทคนิค" การใช้งานจะมีให้ใน repo:
https://github.com/G4Vi/tarsize
ข้อมูลบางอย่างเกี่ยวกับการใช้ LD_PRELOAD: https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/
--totalsได้ ถ้าคุณเติมดิสก์ด้วยวิธีใดคุณก็สามารถลบไฟล์เก็บถาวรได้ทันทีtar --helpในการตรวจสอบตัวเลือกทั้งหมดที่มีอยู่คุณอาจจะผ่านไป