एक पुराने RHEL प्रणाली मुझे मिल गया है पर, /bin/catकरता नहीं के लिए पाश cat x >> x। catत्रुटि संदेश "बिल्ली: x: इनपुट फ़ाइल आउटपुट फ़ाइल है" देता है। मैं मूर्ख कर सकते हैं /bin/catऐसा करने से: cat < x >> x। जब मैं आपके कोड को ऊपर की कोशिश करता हूं, तो मुझे आपके द्वारा वर्णित "लूपिंग" मिलता है। मैंने "बिल्ली" पर आधारित एक सिस्टम कॉल भी लिखा है:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int
main(int ac, char **av)
{
char buf[4906];
int fd, cc;
fd = open(av[1], O_RDONLY);
while ((cc = read(fd, buf, sizeof(buf))) > 0)
if (cc > 0) write(1, buf, cc);
close(fd);
return 0;
}
यह छोरों, भी। यहाँ केवल बफ़रिंग (stdio- आधारित "mycat" के लिए) कर्नेल में क्या होता है।
मुझे लगता है कि क्या हो रहा है कि फाइल डिस्क्रिप्टर 3 (परिणाम open(av[1])) की फाइल में एक ऑफसेट है। 0. डिस्क्रिप्टर 1 (स्टडआउट) में 3 की ऑफसेट है, क्योंकि ">>" इनवॉइसिंग शेल को lseek()ऑन करने का कारण बनता है । फ़ाइल डिस्क्रिप्टर को catचाइल्ड प्रोसेस को सौंपने से पहले ।
read()किसी भी प्रकार का एक करना , चाहे एक stdio बफर में, या एक सादा char buf[]फ़ाइल डिस्क्रिप्टर write()की स्थिति को आगे बढ़ाता है 3. एक एडवांस फ़ाइल डिस्क्रिप्टर की स्थिति को 1 कर रहा है। वे दो ऑफ़सेट अलग-अलग संख्याएँ हैं। ">>" के कारण, फ़ाइल डिस्क्रिप्टर 1 में हमेशा फ़ाइल डिस्क्रिप्टर 3 की ऑफ़सेट की तुलना में अधिक या एक ऑफ़सेट होता है। इसलिए कोई भी "कैट-लाइक" प्रोग्राम लूप करेगा, जब तक कि यह कुछ आंतरिक बफरिंग न करे। यह संभव है, शायद यह भी संभावना है कि, FILE *(जो कि प्रतीकों का प्रकार stdoutऔर fआपके कोड में) का एक stdio कार्यान्वयन है जिसमें अपना स्वयं का बफर शामिल है। fread()वास्तव read()में आंतरिक बफर के लिए एक सिस्टम कॉल कर सकते हैं f। के इनसाइड में यह कुछ भी बदल सकता है या नहीं भी stdout। fwrite()पर बुला रहा हैstdoutअंदर कुछ भी बदल सकता है या नहीं भी f। तो एक stdio- आधारित "बिल्ली" लूप नहीं हो सकता है। या यह हो सकता है। बहुत बदसूरत, बदसूरत libc कोड के माध्यम से पढ़ने के बिना कहना मुश्किल है।
मैंने straceआरएचईएल पर किया था cat- यह सिर्फ read()और write()सिस्टम कॉल का उत्तराधिकार करता है । लेकिन catइस तरह से काम करने की जरूरत नहीं है। यह mmap()इनपुट फ़ाइल के लिए संभव होगा , तब करें write(1, mapped_address, input_file_size)। कर्नेल सभी काम करेगा। या आप sendfile()लिनक्स सिस्टम पर इनपुट और आउटपुट फाइल डिस्क्रिप्टर के बीच एक सिस्टम कॉल कर सकते हैं । पुराने SunOS 4.x सिस्टम को मेमोरी मैपिंग ट्रिक करने के लिए अफवाह थी, लेकिन मुझे नहीं पता कि किसी ने कभी भी सेंडफाइल-आधारित बिल्ली की है। या तो मामले में "लूपिंग" नहीं होगा, दोनों के रूप में write()और sendfile()लंबाई-से-स्थानांतरण पैरामीटर की आवश्यकता होती है।