【问题标题】:Why pthread_getname_np() fails in the thread in Linux?为什么 pthread_getname_np() 在 Linux 的线程中失败?
【发布时间】:2014-01-07 15:43:22
【问题描述】:

这是代码的sn-p。我可以设置线程的名称。但是,在检索线程名称时出现错误。请帮忙。

void *Thread_Function_A(void *thread_arg)
{

  char buf[7];

  int rc;  

  pthread_t self;

  self = pthread_self ();


  rc = pthread_getname_np(self, buf,7);

  if ( rc != 0 )
  cout<<"Failed getting the name"<<endl;

}


int main(int argc, char *argv[])
{
   int rc;
   pid_t thread_pid_val = getpid();
   thread_1.create_thread((thread_1.get_thread_id()), NULL,Thread_Function_A,&thread_pid_val);
   thread_2.create_thread((thread_2.get_thread_id()), NULL,Thread_Function_A,&thread_pid_val);
   rc = pthread_setname_np(*(thread_1.get_thread_id()), "Thread_A");
   if( rc != 0)
   {
     cout<<"Setting name for thread A failed"<<endl; 
   }
   rc = pthread_setname_np(*(thread_2.get_thread_id()), "Thread_B");
   if( rc != 0)
   {
     cout<<"Setting name for thread B failed"<<endl; 
   }
   pthread_join( *(thread_1.get_thread_id()), NULL);
   pthread_join( *(thread_2.get_thread_id()), NULL);

   return  0;   
}

输出:-

$./thread_basic.out 
Failed getting the nameFailed getting the name

The name of thread is The name of thread is 

strerror 说 - 数值结果超出范围 错误=34

现在添加了完整的代码。在这里,我没有设置正确的名称。相反,它检索程序的名称。

void *Thread_Function_A(void *thread_arg)
{

  char name[300];
  char buf[200];

  int rc;  
  char message[100];

  FILE *fp;

  pthread_t self;

  self = pthread_self ();


  rc = pthread_getname_np(self, buf,200);

  if ( rc != 0 )
  {
    cout<<"Failed getting the name"<<endl;
    cerr<<"Pthread get name error ="<<rc<< " " << strerror(rc) << endl;  
  }

  sprintf(name,"log_%s.txt",buf);

  cout<<"The name of thread is "<<buf<<endl;

  fp = fopen(name,"w+");

  for( int i = 1; i<=5; i++)
  {
    sprintf(message,"The thread id is %d  and value of i is %d",pthread_self(),i);

    fprintf(fp,"%s\n", message);
    fflush(fp);
    /** local variable will not be shared actually**/
    /** each thread should execute the loop for 5 **/
    /** total prints should be 10 **/

  }

    pthread_exit(NULL);
}



int main(int argc, char *argv[])
{
   int rc;
   pthread_t threadA, threadB;
   pid_t thread_pid_val = getpid();
   thread_1.create_thread(&threadA, NULL,Thread_Function_A,&thread_pid_val);
   thread_1.set_thread_id(threadA);
   rc = pthread_setname_np(threadA, "Thread_A");
   if( rc != 0)
   {
     cout<<"Setting name for thread A failed"<<endl; 
   }

   thread_2.create_thread(&threadB, NULL,Thread_Function_A,&thread_pid_val);
   thread_2.set_thread_id(threadB);
   rc = pthread_setname_np(threadB, "Thread_B");
   if( rc != 0)
   {
     cout<<"Setting name for thread B failed"<<endl; 
   }
   pthread_join( threadA, NULL);
   pthread_join( threadB, NULL);

   return  0;   
}

输出如下。

]$ ./thread_basic.out 
The name of thread is thread_basic.ou
The name of thread is Thread_B

【问题讨论】:

  • 如果您阅读manual page,您将看到该函数返回错误号(而不是在errno 中设置它),您可能希望打印该错误号(或者使用@987654322 打印可打印字符串@)。
  • 数值结果超出范围是错误。
  • 阅读我在之前评论中链接到的手册页。
  • 此外,这里还有一个竞争条件:如果线程在开始线程有机会分配名称之前到达对pthread_getname_np 的调用,那该怎么办?

标签: c++ linux multithreading linux-kernel pthreads


【解决方案1】:

除了不会让你的调用失败但可能不会返回你想要的东西的竞争条件之外,这就是调用失败的原因。

man 3 pthread_getname_np

pthread_getname_np() 函数可用于检索线程的名称。 thread 参数指定要检索其名称的线程。缓冲区名用于返回线程名; len 指定名称中可用的字节数。 name 指定的缓冲区长度应至少为 16 个字符。输出缓冲区中返回的线程名称将以空值结尾。

char buf[7];

会失败。

【讨论】:

  • 我能够自己纠正它。但是,设置名称存在问题。它没有设置名称。我又要写剧本了。
  • 它没有设置名称,因为您的线程将在您在 main 中设置名称之前结束并完成。这是几个人提到的比赛条件。
  • 用于实验?只需在线程中放置某种延迟(例如睡眠),这样它就可以存活足够长的时间来设置名称。在现实生活中,正常的同步方法集——互斥锁、condvars、信号量等,或者只是将线程名称作为变量传入并拥有线程名称本身。
  • 互斥锁在哪里?我在主函数中设置名称。我正在阅读线程内的名称。如何在阅读之前进行名称设置。我不想使用睡眠。
  • main 获取锁,启动线程,设置名称,解锁。线程已启动但立即阻塞在锁上,直到 main 设置名称并放弃锁。
【解决方案2】:

您正在使用应避免使用的 C 和 C++ 功能的混合,以及我们无法验证的部分代码,例如您的方法 get_thread_id。但是您的代码的问题很明显,您试图过早地获取线程的名称:您的main 没有丝毫机会在线程已经终止之前放置名称。

另外,您的线程函数不正确,任何具有最低警告级别的编译器都应该告诉您。具有非void 返回类型的函数需要return 语句。在 C 语言中,如果你使用函数的返回值,这只会导致未定义的行为,你无法知道,因为它是调用你的函数的线程库。

【讨论】:

  • 解决这种竞争状况的方法是什么?
  • @SHREYASJOSHI,对于这种类型的任何事情,互斥锁和条件变量的组合都是您的朋友。这是 POSIX 中的 方式来协调线程,保证在任何地方都可以工作。
  • 我在 main() 中设置名称,并在线程例程中读取它。如何同步这些事件?
  • @SHREYASJOSHI,我已经回答了这个问题。使用互斥锁和条件变量的组合。如果您不知道这意味着什么,那么是时候记录自己了,如果您使用 POSIX 线程进行编程,这是基本知识。
  • 是的,我明白了。我可以自己让它工作。我知道存在竞争条件,因为 pthread_create 将创建一个线程并且线程例程将启动。但是,线程名称是稍后创建的。锁将确保线程例程不会运行,除非 setname 完成。在线程例程中,只需立即锁定和解锁。
猜你喜欢
  • 2012-10-06
  • 2012-06-08
  • 2023-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-22
  • 2011-04-04
相关资源
最近更新 更多