2015-09-05 3 views
3

Я новичок в тестировании потокового локального хранилища (TLS) с gcc (версия 4.8.2) на моем компьютере Ubuntu 14.04 с архитектурой i686/32 бит.gcc: Thread-локальная переменная, скомпилированная как BSS

В попытке выяснить, имеет ли __thread ключевое слово желаемого эффекта, я скомпилировать этот минималистичный тестовую программу с gcc test.c (без ошибок или предупреждений):

#include <stdio.h> 

__thread int i; 

int main() { 
    i = 7; 
    printf("%d\n",i); 
} 

и использовать инструмент на nm проверить класс хранения символа i в коде объекта:

nm a.out | grep ' i' 

в результате

00000000 B i 

Это означает, что i рассматривается как общая глобальная неинициализированная переменная (хранится в разделе BSS). Согласно man nm, переменные локального хранилища потоков обозначаются буквой L, а не B.

Что здесь не так?

Это проблема nm или проблема?

ответ

5

Там нет никаких проблем, это просто способ nm(1) записывает выходные данные. Формат вывода по умолчанию

nm(1) «S (и информация) отличается между платформами (например, на странице Справочника nm(1) в моем рабочем столе Linux, даже не говоря уже о L для локальной памяти потока).

Однако, если вы включите формат вывода SysV с -fs, вы получите более подробный вывод:

$ nm -fs a.out 
Symbols from a.out: 

Name     Value   Class  Type   Size    Line Section 

... 

i     |0000000000000000| B |    TLS|0000000000000004|  |.tbss 
... 

Как вы можете видеть, используя этот формат вывода i идентифицируется как поток локального в колонке Type, и он живет в .tbss.

Если в man-странице вашего дистрибутива упоминается флаг L для потокового локального хранилища, и вы не видите его в формате вывода по умолчанию, я бы сказал, что это ошибка в nm(1).

+1

Вот и все. Спасибо за объяснение, действительно, я получаю тот же результат. Что касается man-страницы, я был на странице руководства UNIX в Интернете, не понимая. – rplantiko

3

Ваш код слишком низок. Количество потоков не будет известно до выполнения, поэтому переменная, которую вы видите в исполняемом файле, является переменной, которую будет использовать main. Дополнительные копии переменной будут выделены при создании дополнительных потоков.

Вот минимальная программа, которая демонстрирует переменные потока.

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 

__thread int i; 

void *foo(void *args) 
{ 
    i = 8; 
    printf("foo: %d\n", i); 
    return NULL; 
} 

int main(void) 
{ 
    i = 7; 
    printf("main:%d\n", i); 

    pthread_t pid; 
    if (pthread_create(&pid, NULL, foo, NULL) != 0) 
     exit(1); 

    pthread_join(pid, NULL); 
    printf("main:%d\n", i); 
} 
+0

Благодарим вас за этот скелет кода, он действительно будет полезен для программы _real_, которую я имею в виду, чтобы написать! Но для этого вопроса моя проблема была больше связана с пониманием вывода «nm», так что Филипе Гонсалвис понял это (он показал мне, как проверить класс хранения с помощью «nm -fs»). – rplantiko

Смежные вопросы