2010-08-23 19 views
5

निम्नलिखित स्निपेट के लिए,कंपाइलर कैसे जानता है कि आपके द्वारा उपयोग किया जाने वाला फ़ंक्शन सिस्टम कॉल है?

int n; 
char buf[100]; 
int fd = open ("/etc/passwd", O_RDONLY); 
n = read (fd, buf, 100); 

कैसे संकलक पता चला है कि पढ़ने के लिए एक सिस्टम कॉल नहीं किसी भी पुस्तकालय समारोह है आता है?

यह सिस्टम कॉल नंबर (__NR_read) को कैसे पुनर्प्राप्त करता है?

उत्तर

1

खुला() एक पुस्तकालय समारोह, यह

13

मुझे बहुत संदेह है कि कंपाइलर जानता है कि यह एक सिस्टम कॉल है। यह कहीं अधिक संभावना है कि open कहीं लाइब्रेरी में है और लाइब्रेरी के भीतर कोड प्रासंगिक कर्नेल इंटरफ़ेस को कॉल करता है।

साधारण प्रोग्राम से विधानसभा उत्पादन:

#include <stdio.h> 
int main (void) { 
    int fd = open("xyz"); 
    return 0; 
} 

(अप्रासंगिक बिट्स निकाला गया) है:

main: 
    pushl %ebp   ; stack frame setup. 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $32, %esp 

    movl $.LC0, (%esp) ; Store file name address. 
    call open   ; call the library function. 
    movl %eax, 28(%esp) ; save returned file descriptor. 

    movl $0, %eax  ; return 0 error code. 

    leave     ; stack frame teardown. 
    ret 

.LC0: 
    .string "xyz"   ; file name to open. 

पहली बात आप ध्यान देंगे कि वहाँ एक कॉलopen है। दूसरे शब्दों में, यह एक समारोह है। दृष्टि में int 80 या sysenter नहीं है, जो कि उचित सिस्टम कॉल (मेरे प्लेटफॉर्म पर वैसे भी - वाईएमएमवी) के लिए उपयोग की जाने वाली तंत्र है।

libc में रैपर फ़ंक्शन हैं जहां सिस्टम कॉल इंटरफ़ेस तक पहुंचने का वास्तविक कार्य किया जाता है।

system calls पर विकिपीडिया से एक अंश:

आम तौर पर, सिस्टम एक पुस्तकालय है कि इस तरह glibc के रूप में सामान्य कार्यक्रमों और ऑपरेटिंग सिस्टम है, आमतौर पर सी पुस्तकालय (libc) के एक कार्यान्वयन, के बीच बैठता है प्रदान करते हैं। यह पुस्तकालय ओएस और एप्लिकेशन के बीच मौजूद है, और पोर्टेबिलिटी बढ़ जाती है।

exokernel आधारित सिस्टम पर, पुस्तकालय विशेष रूप से मध्यस्थ के रूप में महत्वपूर्ण है। Exokernels पर, पुस्तकालय बहुत कम स्तर कर्नेल एपीआई से उपयोगकर्ता अनुप्रयोग ढाल, और abstractions और संसाधन प्रबंधन प्रदान करते हैं।

शब्द "सिस्टम कॉल" और "syscall" अक्सर सी मानक लाइब्रेरी फ़ंक्शंस को संदर्भित करने के लिए गलत तरीके से उपयोग किए जाते हैं, विशेष रूप से वे जो एक ही नाम के साथ संबंधित सिस्टम कॉल के लिए एक रैपर के रूप में कार्य करते हैं। लाइब्रेरी फ़ंक्शन को कॉल करने से कॉल कर्नेल मोड में स्विच नहीं होता है (यदि निष्पादन पहले से ही कर्नेल मोड में नहीं था) और आमतौर पर सामान्य सबराउटिन कॉल होता है (यानी, कुछ आईएसए में "कॉल" असेंबली निर्देश का उपयोग करके)। वास्तविक सिस्टम कॉल कर्नेल को ट्रांसफर कंट्रोल करता है (और लाइब्रेरी कॉल से अधिक कार्यान्वयन-निर्भर है)। उदाहरण के लिए, fork और execve जीएलबीबीसी फ़ंक्शन हैं जो बदले में fork और execve सिस्टम-कॉल पर कॉल करते हैं।

और, खोज का एक सा के बाद, __open समारोह io/open.c फाइल में glibc 2.9 में पाया जाता है, और weakref 'open को एड।यदि आप निष्पादित करें:

nm /usr/lib/libc.a | egrep 'W __open$|W open$' 

तुम वहाँ में उन्हें देख सकते हैं:

00000000 W __open 
00000000 W open 
+0

खुला सिस्टम कॉल भी है। किसी पुस्तकालय में खोलने के लिए कोई कोड नहीं है। कैसे संकलक खुला कॉल के लिए हल करता है? –

+0

ऐसा नहीं, अद्यतन देखें। – paxdiablo

+0

आइए कहें, मैंने अपना सिस्टम कॉल डाला और कर्नेल को संकलित किया जिसमें libc में wrapper function नहीं है। –

6

पढ़ने जहाँ तक संकलक का सवाल है एक पुस्तकालय कॉल है। ऐसा ही होता है कि libc कार्यान्वयन सही संख्या के साथ सॉफ़्टवेयर बाधा उत्पन्न करने के लिए पढ़ता है।

+0

मुझे नहीं लगता कि libc में कोई भी पढ़ा गया कार्यान्वयन है? –

+7

@ गणेश कुंडापुर हां वहाँ है। सभी सिस्टम कॉल libc फ़ंक्शंस में लिपटे हैं। (और यदि आप स्वयं को सिस्कल बनाना चाहते हैं तो एक सामान्य syscall() फ़ंक्शन है) – nos

2

कंपाइलर इस फ़ंक्शन की घोषणा देख सकता है, और यह ऑब्जेक्ट कोड उत्पन्न करता है जो उस फ़ंक्शन को कॉल करता है।

gcc -S साथ संकलन की कोशिश करो और आप देखेंगे कुछ की तरह:

movl $100, %edx 
movq %rcx, %rsi 
movl %eax, %edi 
call read 

सिस्टम कॉल पढ़ने के सी पुस्तकालय के कार्यान्वयन से बनाया गया है (2)।

संपादित करें: विशेष रूप से, जीएनयू libc (जो कि आपके पास लिनक्स पर है) की संभावना है, glibc-2.12.1/sysdeps/syscalls.list में सिस्कोल संख्याओं और फ़ंक्शन नामों के बीच संबंध स्थापित करता है। उस फ़ाइल की प्रत्येक पंक्ति को एक असेंबली भाषा स्रोत कोड (sysdeps/unix/syscall-template.S पर आधारित) में परिवर्तित किया गया है, संकलित किया गया है, और libc बनाया गया है जब लाइब्रेरी में जोड़ा गया है।

+0

हाँ, लेकिन आंतरिक रूप से यह पढ़ने के लिए सिस्टम कॉल नंबर (__NR_read) को पुनर्प्राप्त करता है और syscall (__ NR_read, fd, buf) के रूप में कॉल करता है , 100); –

+1

@ गणेश कुंडापुर: संपादित करें देखें। सिस्टम कॉल "आंतरिक रूप से पुनर्प्राप्त नहीं" है, इसे libc में संकलित किया गया है। – Cubbi

1

निम्नलिखित libc.so/libc.a में स्थित है बायोनिक में पढ़ा के एंड्रॉयड कार्यान्वयन (libc के लिए एंड्रॉयड बराबर)

/* autogenerated by gensyscalls.py */ 
#include <sys/linux-syscalls.h> 

    .text 
    .type read, #function 
    .globl read 
    .align 4 
    .fnstart 

read: 
    .save {r4, r7} 
    stmfd sp!, {r4, r7} 
    ldr  r7, =__NR_read 
    swi  #0 
    ldmfd sp!, {r4, r7} 
    movs r0, r0 
    bxpl lr 
    b  __set_syscall_errno 
    .fnend 

आप देख सकते हैं कि यह __NR_read को r7 में लोड करता है और फिर एसडब्ल्यूआई को कॉल करता है, एसडब्ल्यूआई सॉफ़्टवेयर इंटरप्ट होता है जो प्रिंटर को कर्नेल मोड में बदल देता है। इसलिए संकलक को सिस्टम कॉल करने के बारे में कुछ भी नहीं पता होना चाहिए, libc इसका ख्याल रखता है।

संबंधित मुद्दे

 संबंधित मुद्दे