ถ้าความเร็วเป็นสิ่งที่สำคัญและการบีบอัดไม่จำเป็นต้องคุณสามารถขอห่อ 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
ในการตรวจสอบตัวเลือกทั้งหมดที่มีอยู่คุณอาจจะผ่านไป