linux_thread basic function-pthread_self function-pthread_create function-pthread_exit function-pthread_join function

Continued from the previous article: linux_Thread Concept-Kernel Thread Implementation Principle-Thread Shared Resources-Thread Advantages and Disadvantages

  Today I’m going to share the code functions of threads, mainly to obtain thread ID, create thread function, thread exit function, wait for thread end function, and share examples of these functions. Without further ado, let’s start serving:

The catalog of articles published by this blogger on CSDN: My CSDN catalog, as a guide to the types of articles published by bloggers on CSDN

1.pthread_self function

Function:
  Get the thread ID. Its role corresponds to the getpid() function in the process.
Header file:
  #include <pthread.h>
Function prototype:
  pthread_t pthread_self(void);
Function parameters:
  None
Return value:
  Success: Return the ID number of the thread;
Failure: None!
Note:
  ① When g++/gcc is compiled, the parameter -lpthread needs to be added to compile the pthread dynamic library.
  ② The global variable pthread_t tid should not be used, and the thread ID should be obtained by passing parameters through pthread_create in the child thread, but pthread_self should be used.
  ③Thread ID: pthread_t type, which can be understood as: typedef unsigned long int pthread_t; essence: it is an unsigned integer (%lu) under Linux, and may be realized by a structure in other systems ④Thread ID is an identification mark inside the process
   . (The thread ID is allowed to be the same between two processes)

2.pthread_create function

Function role:
  Create a new thread. Its function corresponds to the fork() function in the process.
Header file:
  #include <pthread.h>
Function prototype:
  int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); Function parameter:
thread
  : outgoing parameter, Save the thread ID assigned to us by the system.
  attr: Usually pass NULL, which means using the default attribute of the thread. You can also modify this parameter if you want to use specific attributes.
  start_routine: function pointer, pointing to the thread main function (thread body). When the function finishes running, the thread ends, that is, the callback function for creating the thread.
  arg: The parameters used during the execution of the thread's main function.
Return value:
  success: 0;
  failure: error number, the error information can be printed through the strerror function.

  After calling pthread_create() in a thread to create a new thread, the current thread returns from pthread_create() and continues to execute, and the code executed by the new thread is determined by the function pointer start_routine we pass to pthread_create.
  The start_routine function receives a parameter, which is passed to it through the arg parameter of pthread_create. The type of the parameter is void *, and the type of interpretation of this pointer is defined by the caller.
  The return value type of start_routine is also void *, and the meaning of this pointer is also defined by the caller.
  When start_routine returns, the thread exits. Other threads can call pthread_join to get the return value of start_routine, which is similar to the parent process calling wait(2) to get the exit status of the child process. We will introduce pthread_join in detail later.

  After pthread_create returns successfully, the id of the newly created thread is filled in the memory unit pointed to by the thread parameter.
  We know that the type of process id is pid_t, and the id of each process is unique in the entire system. Call getpid(2) to get the id of the current process, which is a positive integer value. The type of thread id is thread_t, which is guaranteed to be unique only in the current process. In different systems, the thread_t type has different implementations. It may be an integer value, a structure, or an address , so it cannot be simply printed with printf as an integer, and the id of the current thread can be obtained by calling pthread_self(3).
  Since the error code of pthread_create is not stored in errno, the error message cannot be printed directly with perror(3). You can use strerror(3) to convert the error code into an error message before printing.

2.1. Threads and sharing

First throw the conclusion: global variables are shared between threads!

3.pthread_exit function

Function:
  Exit a single thread.
Header file:
  #include <pthread.h>
Function prototype:
  void pthread_exit(void *retval);
Function parameters:
  retval: Indicates the thread exit status, usually pass NULL.
Return value:
  None.
Note:
  In threads, the use of the exit function is prohibited, which will cause all threads in the process to exit.
  Without adding sleep to control the output order. In the loop, pthread_create creates 5 threads almost instantaneously, but only the first thread has a chance to output (or the second one also has it, or it may not, depending on the kernel scheduling). If the third thread executes exit, the entire process will exit , so all threads exited.
  Therefore, in a multi-threaded environment, it should be used as little as possible, or the exit function should not be used, and the pthread_exit function should be used instead to exit a single thread. Exit in any thread causes the process to exit, and other threads have not finished their work. When the main control thread exits, it cannot return or exit.
  Also note that the memory unit pointed to by the pointer returned by pthread_exit or return must be global or allocated by malloc, and cannot be allocated on the stack of the thread function, because the thread function has already exited when other threads get the return pointer.

Summary of thread calls return, pthread_exit, and exit:
   return: return to the caller.
   pthread_exit(): The thread that will call this function
   exit: Exit the process.

4.pthread_join function

Function:
  Block and wait for the thread to exit, get the exit status of the thread.
Header file:
  #include <pthread.h>
Function prototype:
  int pthread_join(pthread_t thread, void **retval);
Function parameters:
  thread: thread ID ([Note]: not a pointer);
  retval: store thread end status.
Return value:
  success: 0;
  failure: error number, the error information can be printed through the strerror function.
Note:
  The thread calling this function will hang and wait until the thread whose id is thread terminates. The thread thread is terminated in different ways, and the termination status obtained through pthread_join is different. The summary is as follows:
  1. If the thread thread returns through return, the unit pointed to by retval stores the return value of the thread thread function.
  2. If the thread thread is abnormally terminated by another thread calling pthread_cancel, the constant PTHREAD_CANCELED is stored in the unit pointed to by retval.
  3. If the thread thread is terminated by calling pthread_exit by itself, the unit pointed to by retval stores the parameters passed to pthread_exit.
  4. If you are not interested in the termination status of the thread thread, you can pass NULL to the retval parameter.

5. Examples of function calls:

5.1.pthread_self function - pthread_create function - create multi-thread

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
//通过命令:ps -Lf PID #查看PID进程下的线程
void *tfn(void *arg)
{
    
    
	int i;
	i = (int)arg;
	sleep(i);	 //通过i来区别每个线程
	printf("我是第%d个线程, 线程ID = %lu\n", i+1, pthread_self());
	return NULL;
}
int main(int argc, char *argv[])
{
    
    
	int n = 5, i;
	pthread_t tid;
    //创建5个进程
	for (i = 0; i < n; i++) 
	{
    
    
		pthread_create(&tid, NULL, tfn, (void *)i);
		//将i转换为指针,在tfn中再强转回整形。
	}
	sleep(n);//程序暂停5s
	printf("主线程ID == %lu\n", pthread_self());

	return 0;
}

5.2. strerror function - check how many threads the system can create at most

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
//线程回调函数
void *tfn(void *arg)
{
    
    
    while (1)
        sleep(1);
}
int main(void)
{
    
    
	pthread_t tid;
	int ret, count = 1;
	//循环一直创建,直至程序错误退出,检验你的系统最多创建多少个线程
	for (;;) {
    
    
		ret = pthread_create(&tid, NULL, tfn, NULL);
		if (ret != 0) 
		{
    
    
			printf("%s\n", strerror(ret));
			break;
		}
		printf("---------%d---------------\n", ++count);
	}
	return 0;
}

5.3. Sharing global variables between threads

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

int var = 100;
//线程回调函数
void *tfn(void *arg)
{
    
    
	var = 200;
	printf("线程回调函数...\n");
	return NULL;
}

int main(void)
{
    
    
	printf("改变之前:var = %d\n", var);//var=100
	pthread_t tid;
	pthread_create(&tid, NULL, tfn, NULL);//创建线程
	sleep(1);
	printf("改变之后:var = %d\n", var);//var=200
	return 0;
}

5.4.pthread_exit function call - end thread

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
//线程回调函数
void *tfn(void *arg)
{
    
    
	int i;
	i = (int)arg; //强转。
	if (i == 2)
	{
    
    
		pthread_exit(NULL);//结束线程
	}
	sleep(i);	 //通过i来区别每个线程
	printf("我是第%d个线程, 线程ID = %lu\n", i+1, pthread_self());
	return NULL;
}
int main(int argc, char *argv[])
{
    
    
	int n = 5, i;
	pthread_t tid;
	for (i = 0; i < n; i++) 
	{
    
    
		pthread_create(&tid, NULL, tfn, (void *)i);//将i转换为指针,在tfn中再强转回整形。
	}
	sleep(n);
	printf("主控线程ID = %lu\n", pthread_self());
	return 0;
}

5.5.pthread_join function call - get the return value of thread exit

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
//自定义返回值
typedef struct {
    
    
	int a;
	int b;
} exit_t;
//线程回调函数
void *tfn(void *arg)
{
    
    
	exit_t *ret;
	ret = malloc(sizeof(exit_t)); //分配内存
	//改变值
	ret->a = 100;
	ret->b = 300;
	pthread_exit((void *)ret);
}
int main(void)
{
    
    
	pthread_t tid;
	exit_t *retval = NULL;
	pthread_create(&tid, NULL, tfn, NULL);
	//调用pthread_join可以获取线程的退出状态
	pthread_join(tid, (void **)&retval); //等待线程退出
	printf("a = %d, b = %d \n", retval->a, retval->b);//打印线程退出的返回值
	free(retval);//释放内存
	retval = NULL;//置NULL
	return 0;
}

5.6. Get the return value of multithreading

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
int var = 100;
//线程回调函数
void *tfn(void *arg)
{
    
    
    int i;
    i = (int)arg;
    sleep(i);//线程暂定is
    if (i == 1) 
	{
    
    
        var = 333;
        printf("第%d个线程:var = %d\n", i+1,var);
        return (void *)var;
    } 
	else  if (i == 3) 
	{
    
    
        var = 777;
        printf("第%d个线程:var = %d\n", i+1, var);
        pthread_exit((void *)var);

} 
else  {
    
    
        printf("第%d个线程:var = %d\n", i+1, var);
        pthread_exit((void *)var);
    }

    return NULL;
}
int main(void)
{
    
    
    pthread_t tid[5];
    int i;
    int *ret[5];  
	//创建5个线程
    for (i = 0; i < 5; i++)
	{
    
    
        pthread_create(&tid[i], NULL, tfn, (void *)i);
	}
    for (i = 0; i < 5; i++) 
	{
    
    
		//通过pthread_join获取线程返回状态
        pthread_join(tid[i], (void **)&ret[i]);
        printf("第%d个线程返回:%d\n", i+1, (int)ret[i]);
    }
    printf("主线程ID = %lu\t var = %d\n", pthread_self(), var);
    sleep(i);
    return 0;
}

The above is the sharing of this time, I hope it will be helpful to everyone, welcome to follow the blogger to learn more new knowledge together!

Guess you like

Origin blog.csdn.net/qq_44177918/article/details/130442584