Добрый день. Не смог найти ответа на вопрос. В хедерах Линухи (например в unistd.h и в других) приводятся объявления POSIX API: ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); и т.д. POSIX API или System Interface, как я выяснил, это wrapper functions над системными вызовами ядра (syscalls). Вопрос - где искать реализацию (implementation) этих POSIX API? Я думаю в исходниках glibc, должна быть, но могу и ошибаться. Мне необходимо проследить путь от вызова API до сискола ядра, с целью сравнения двух схожих API. Наверное между этими точками выполняется море кода из обёрток
Я в шоке... glibc, файл - sendto.c Код (Text): ssize_t __sendto (fd, buf, n, flags, addr, addr_len) int fd; __const __ptr_t buf; size_t n; int flags; __CONST_SOCKADDR_ARG addr; socklen_t addr_len; { __set_errno (ENOSYS); return -1; } Что за кодстайл? Венгерская нотация не соблюдается. Какие-то подчёркивания перед именами, непонятно с какого перепуга взявшиеся (__sendto). Код читать невозможно... Это разве определение функции? Почему типы аргументов не указываются перед переменными в круглых скобках? Почему разрабы glibc выбрали именно такой непонятный стиль и где документированы эти нюансы?
Это кроссплатформенная либа, компилируемая кучей компиляторов под различные целевые операционные и процессорные системы. Так что не пугайтесь __sendto -- это скорее всего просто имя обёртки
Оу, человек впервые добрался до кроссплатформенных стандартных хидеров. Конец немного предсказуем - http://lurkmore.ru/Shit_bricks
Nafanya Чего вы хотите от Си? Это кроссплатформенный ассемблер, хотите иного - юзайте типобезопасные языки, к примеру С++. Про венгерскую нотацию даже не заикайтесь - закопать не думая.
Booster Сейчас склонировал репозиторий glibc с git://sourceware.org/git/glibc.git на свою локальную тачку. Исходные тексты в репозитории те же самые, как и в архиве. Оказывается действительно разработчики развивают и поддерживают дерево в таком виде. Куча макросов и странности в именовании идентификаторов их не смущают. Продукт развивается, вот фото с системы контроля версий glibc: Видимо дело во мне, судя по фото - процесс разработки и фиксинга баг идёт непрерывно для glibc - значит другие программисты без затруднений читают такой кроссплатформенный код.
Ребята, может кто знает какие IDE применяют для навигации по огромным проектам (например - репозиторий glibc ~230 MB, Linux Kernel > полгига)? Студия уже не справляется, виснет, тормозит. Хотя по проекту с исходниками около 1,5 мегабайт навигация идёт очень шустро - моментальный переход от вызова функции к её определению. И ещё в огромных проектах - большая вложенность директорий с исходниками, а Студия видимо не поддерживает рекурсивный поиск headers и sources по вложенным каталогам при парсинге. Ищет только в путях прописанных в Include Directories и Sources Directories
man ctags man cscope etags для emacs Билдовая система ядра может делать тэг-файлы, make help в помощь.
7mm Спасибо, заюзал cscope. Если у вас есть исходники glibc, прошу взглянуть на следующий феномен. POSIX API sendto(): sendto() -> __sendto -> __socket_send() Всё цепочка обрывается - ни cscope, ни grep, ни Студия не может найти определения wrapper-function: __socket_send(). Она только вызывается, но нет ни #define __socket_send ..., ни определения этой обёртки - какая-то функция-призрак.
sendto.c - body of __sendto() wrapper function: Код (Text): ssize_t __sendto (int fd, const void *buf, size_t n, int flags, const struct sockaddr_un *addr, socklen_t addr_len) { addr_port_t aport; error_t err; size_t wrote; if (addr->sun_family == AF_LOCAL) { /* For the local domain, we must look up the name as a file and talk to it with the ifsock protocol. */ file_t file = __file_name_lookup (addr->sun_path, 0, 0); if (file == MACH_PORT_NULL) return -1; err = __ifsock_getsockaddr (file, &aport); __mach_port_deallocate (__mach_task_self (), file); if (err == MIG_BAD_ID || err == EOPNOTSUPP) /* The file did not grok the ifsock protocol. */ err = ENOTSOCK; if (err) return __hurd_fail (err); } else err = EIEIO; /* Get an address port for the desired destination address. */ err = HURD_DPORT_USE (fd, ({ if (err) err = __socket_create_address (port, addr->sun_family, (char *) addr, addr_len, &aport); if (! err) { /* Send the data. */ err = __socket_send (port, aport, flags, buf, n, NULL, MACH_MSG_TYPE_COPY_SEND, 0, NULL, 0, &wrote); //HERE WE CALL __socket_send FUNCTION!!! __mach_port_deallocate (__mach_task_self (), aport); } err; })); return err ? __hurd_sockfail (fd, flags, err) : wrote; } weak_alias (__sendto, sendto) Где в glibc определение (тело) __socket_send функции? Поиск по всем файлам результата не дал. Вызывать функции без тела нельзя, а она вызывается. Как разрешить это противоречие?
А вас не смущает, что вы смотрите в исходниках для HURD?... Код (Text): im@r00tbox:~/projects/glibc$ grep -r -n "__socket_send" ./* ./ChangeLog.4:1860: * sysdeps/mach/hurd/send.c: Fix portsPoly arg to __socket_send. ./sysdeps/mach/hurd/sendmsg.c:144: err = __socket_send (port, aport, ./sysdeps/mach/hurd/sendto.c:71: err = __socket_send (port, aport, ./sysdeps/mach/hurd/send.c:36: err = HURD_DPORT_USE (fd, __socket_send (port, MACH_PORT_NULL, Код (Text): im@r00tbox:~/projects/glibc$ grep -r -n "__socket_create_address" ./* ./sysdeps/mach/hurd/sendmsg.c:136: err = __socket_create_address (port, ./sysdeps/mach/hurd/sendto.c:63: err = __socket_create_address (port, ./sysdeps/mach/hurd/connect.c:61: err = __socket_create_address (port, ./sysdeps/mach/hurd/bind.c:109: err = __socket_create_address (port,
7mm Можно поподробнее Вашу мысль? Вам удалось найти в glibc тела для следующих функций? 1)__socket_send() 2)__libc_sendto() - это псевдоним для __sendto() Мне нет.
/socket/sendto.c - Тихий ужас. Код (Text): /* Send N bytes of BUF on socket FD to peer at address ADDR (which is ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */ ssize_t __sendto (fd, buf, n, flags, addr, addr_len) int fd; __const __ptr_t buf; size_t n; int flags; __CONST_SOCKADDR_ARG addr; socklen_t addr_len; { __set_errno (ENOSYS); return -1; } weak_alias (__sendto, sendto) Зачем это? Чтобы вместо отправки данных в сокет API sendto() сообщала об ошибке? Такой реализации я не ожидал...
glibc/sysdeps/unix/sysv/linux/x86_64/send.c Код (Text): #include <errno.h> #include <sys/socket.h> #include <sysdep-cancel.h> /* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ ssize_t __libc_send (int fd, const void *buf, size_t n, int flags) { if (SINGLE_THREAD_P) return INLINE_SYSCALL (sendto, 6, fd, buf, n, flags, NULL, (size_t) 0); int oldtype = LIBC_CANCEL_ASYNC (); ssize_t result = INLINE_SYSCALL (sendto, 6, fd, buf, n, flags, NULL, (size_t) 0); LIBC_CANCEL_RESET (oldtype); return result; } weak_alias (__libc_send, __send) libc_hidden_weak (__send) weak_alias (__send, send) __send weak alias для __libc_send * Вопрос в том, зачем вы смотрите в исходниках для HURD?
Это функция-заглушка, для того, чтобы если система не поддерживает операции с сокетами, то по запросу операции выдавалась бы ошибка. Смотрите weak_alias и __attribute__ weak для функций в gcc.
7mm Так мне необходимо добраться до syscall'а ядра для API sendto() , а у ВАС: weak_alias (__libc_send, __send) libc_hidden_weak (__send) weak_alias (__send, send) Это API send(). Но всё равно спасибо.