Понимание соглашений исходного кода glibc - PullRequest
8 голосов
/ 14 марта 2012

Я искал некоторый исходный код для glibc, в частности код nptl, и нашел его немного сложным для понимания, так как он, кажется, имеет соглашения, с которыми я не знаком.

Например, я искал очень маленький файл pthread_equal.c , и у меня есть несколько вопросов, по которым у меня возникли вопросы:

22 int
23 __pthread_equal (thread1, thread2)
24      pthread_t thread1;
25      pthread_t thread2;
26 {
27   return thread1 == thread2;
28 }
29 strong_alias (__pthread_equal, pthread_equal)
  1. Объявление в строках 22 и 23 выглядит, как я понимаю. Он имеет тип возврата int, затем имя функции __pthread_equal и список параметров (thread1, thread2). Но для чего нужны объявления в строках 24 pthread_t thread1; и 25 pthread_t thread2;? Похоже, они объявляются как глобальные переменные, но я не понимаю цели. Я видел этот шаблон во многих файлах в каталоге nptl и не смог понять, почему это делается.

  2. Что такое strong_alias? Быстрый поиск в Google содержит примеры этого, но я не нашел ссылки на какую-либо документацию.

  3. В чем причина того, что некоторые имена начинаются с двух подчеркиваний __, а некоторые с одним подчеркиванием _. Большая часть кода, который я видел, использует два подчеркивания, но я думаю, что я видел некоторые места, где используется одно подчеркивание. Например, в pthreadP.h

    556 /* Old cleanup interfaces, still used in libc.so.  */
    557 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
    558                                    void (*routine) (void *), void *arg);
    559 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
    560                                   int execute);
    561 extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
    562                                          void (*routine) (void *), void *arg);
    563 extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
    564                                           int execute);
    

По общему признанию, этому коду предшествует комментарий, в котором говорится "старые интерфейсы очистки", но в любом случае мне любопытно различие и почему иногда используется одно подчеркивание, а иногда два подчеркивания.

Любая информация по этим вопросам приветствуется.

Ответы [ 2 ]

9 голосов
/ 14 марта 2012

Функция написана без использования C89-совместимого компилятора; это будет работать и со старыми компиляторами. Это непрототипное определение функции.

int   /* Return type */
function(arg1, arg2)    /* Function name and argument names (but no types) */
    int arg1;    /* Type of arg1 */
    char *arg2;  /* Type of arg2 */
{
    /* Body of function */
}

Обратите внимание, что определения аргументов не обязательно должны быть в той же последовательности, что и в функциональной строке (мне пришлось преобразовать код из этой нотации K & R в нотацию прототипа, где они были не в порядке!). Также обратите внимание, что раньше можно было просто написать:

main(argc, argv)
    char **argv;
{
    ...
}

Предполагаемый тип для argc был int, так как он не был указан как что-либо еще. Маловероятно, что код glib использует эту лицензию. Аналогично, тип возвращаемого значения main() был int, потому что другого типа не было.

strong_alias относится к сокрытию и отображению символов в общих библиотеках. Я не использовал его, поэтому я не уверен во всех последствиях, но я считаю, что это означает, что __pthread_equal() - это другое название функции pthread_equal().


Одна из причин, стоящих за именем __pthread_equal(), заключается в том, что имена, начинающиеся с символа подчеркивания, за которым следует заглавная буква или другое подчеркивание, «зарезервированы для реализации» в стандарте C. Такие имена, как pthread_equal (), находятся в пространстве имен пользователей в соответствии со стандартом C.

ISO / IEC 9899: 1990 (стандарт C99) гласит:

7.1.3 Зарезервированные идентификаторы

Каждый заголовок объявляет или определяет все идентификаторы, перечисленные в соответствующем подпункте, и опционально объявляет или определяет идентификаторы, перечисленные в соответствующих направлениях будущей библиотеки подпункт и идентификаторы, которые всегда зарезервированы либо для любого использования, либо для использования в качестве файла идентификаторы области.

- Все идентификаторы, которые начинаются с символа подчеркивания и заглавной буквы или другого подчеркивание всегда зарезервировано для любого использования.

- Все идентификаторы, которые начинаются с подчеркивания, всегда зарезервированы для использования в качестве идентификаторов с областью действия файла как в обычном пространстве, так и в пространстве имен тегов.

- имя каждого макроса в любом из следующих подпунктов (включая будущую библиотеку) направления) зарезервировано для использования, как указано, если включен какой-либо из связанных с ним заголовков; если прямо не указано иное (см. 7.1.4).

- Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотеки) всегда зарезервированы для использования в качестве идентификаторов с внешними связь. 154)

- Каждый идентификатор с областью действия файла указан в любом из следующих подпунктов (включая будущие направления библиотеки) зарезервировано для использования в качестве имени макроса и в качестве идентификатора с область файла в том же пространстве имен, если включен какой-либо из связанных с ним заголовков.

Другие идентификаторы не зарезервированы. Если программа объявляет или определяет идентификатор в контекст, в котором он зарезервирован (кроме как разрешено в 7.1.4), или определяет зарезервированный идентификатор в качестве имени макроса, поведение не определено.

154) Список зарезервированных идентификаторов с внешней связью включает errno, math_errhandling, setjmp и va_end.

2 голосов
/ 14 марта 2012
  1. Старая запись.
  2. Для обеспечения типа __pthread_equal, pthread_equal к тому же.
  3. Чтобы различать имена переменных и различать базовую область и пользовательскую область.
...