要使 getenv_r 可重入,需要改變接口,調用者必須自己提供緩沖區,這樣每個線程可以使用各自不同的緩沖區從而避免其他線程的干擾。但是注意這還不足以使 getenv_r 成為線程安全的,要使 getenv_r 成為線程安全的, 需要在搜索請求的字符串時保護環境不被修改。我們可以使用互斥量,通過 getenv_r 和 putenv 函數對環境列表的訪問進行序列化。
#include
#include
#include
#include
#include
#include
#define ARG_MAX 100
#define BUFSIZE 100
extern char **environ;
pthread_mutex_t env_mutex;
static pthread_once_t init_done = PTHREAD_ONCE_INIT;
static void thread_init(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&env_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
int getenv_r(const char *name, char *buf, int buflen)
{
int i, len, olen;
pthread_once(&init_done, thread_init);
len = strlen(name);
pthread_mutex_lock(&env_mutex);
for (i=0; environ[i]; i++) {
if ((strncmp(name, environ[i], len) == 0) && environ[i][len] == '=') {
olen = strlen(&environ[i][len+1]);
if (olen >= buflen) {
pthread_mutex_unlock(&env_mutex);
return ENOSPC;
}
strcpy(buf, &environ[i][len+1]);
pthread_mutex_unlock(&env_mutex);
return 0;
}
}
pthread_mutex_unlock(&env_mutex);
return ENOENT;
}
void *thr_func(void *arg)
{
char buf[BUFSIZE];
int err;
err = getenv_r(arg, buf, BUFSIZE);
if (err != 0) {
printf("thread 1: %s\n", strerror(err));
return (void *)1;
}
printf("thread 1: %s\n", buf);
return (void *)0;
}
int main()
{
int err, tid;
err = pthread_create(&tid, 0, thr_func, "SHELL");
if (err != 0) {
printf("can't create thread\n");
exit(1);
}
char buf[BUFSIZE];
err = getenv_r("JOB", buf, BUFSIZE);
if (err != 0) {
printf("main part: %s\n", strerror(err));
exit(1);
}
printf("main part: %s\n", buf);
sleep(1);
return 0;
}