Introduction of threads:

Because the address space of the process is private, the system overhead is high when switching. In order to solve this problem and improve the performance of the system, the concept of lightweight process is introduced, and this lightweight process is called thread.

The difference between a process and a thread

Processes are the basic unit of system resource allocation

Thread is the basic unit of system task scheduling

Thread resources

1. A process can have multiple threads sharing the following resources

(1) static data (2) file descriptors opened by the process (3) signal processing functions (4) current path (5) executable instructions (6) User ID and user group IDCopy the code

2. Private resources for each thread

(1) thread ID (2) program counters and related registers (3) local variables in thread task functions (4) error number: errno (5) information mask (6) execution state and thread attributes of the thread itselfCopy the code

Thread API functions

GCC 1.c -o 1-lpThread GCC 1.c -o 1-lpthread GCC 1.c -o 1-lpthread

(1) Thread creation

Thread routine functions need to be defined, the function interface is as follows:

void *routine(void *arg)
{
}
Copy the code

(two) combined with the specified thread

Retval can be specified as NULL if the thread exits without an exit value. 2, pthread_join() will block waiting if the thread is still running. Pthread_tryjoin_np () will return an error immediately if the thread is still running.Copy the code

(3) Thread exit

Note: Local variables are released when the function exits. If the thread function needs to return data, it must ensure that the data exit function is still valid. Therefore, we recommend using either static data or heap space pthread_exit() to exit the thread, not the main process

(4) Passive withdrawal:

The sample code

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

void *routine(void *arg)
{
	int i = 0;
	while(1)
	{
		printf("i = %d\n", i++);
		sleep(1); }}int main(int argc, char const *argv[])
{
	int a = 20;
	pthread_t pid;
	// Create a thread
	pthread_create(&pid, NULL, routine, (void *)(&a));

	pthread_t pid1;
	pthread_create(&pid1, NULL, routine, (void *)(&a));
	
	// pthread_cancel(pid);

	sleep(4);
	pthread_cancel(pid);
	sleep(5);
	pthread_cancel(pid1);
	pthread_join(pid, NULL);
	return 0;
}
Copy the code

Running results:

Thread properties (Understood)

(1) Separation attribute (2) scheduling policy (3) stack size and alert area sizeCopy the code

Thread property functions use steps

1. Define thread attribute variables and initialize them with pthread_attr_init().

    pthread_attr_t attr; pthread_attr_init(attr );
Copy the code

2. Use pthread_attr_setXXX() to set the related properties.

3. Create the corresponding thread using the thread attribute variable.

4, use pthread_attr_destroy() to destroy the thread attribute variable.

    pthread_attr_destroy(attr );
    #include <pthread.h>
    int pthread_attr_init(pthread_attr_t *attr);
    int pthread_attr_destroy(pthread_attr_t *attr);
Copy the code

Separate attributes:

(1) Split: make pthread_JOIN invalid, thread exit will not enter zombie state, no outgoing data (2) join: the reverse.Copy the code

2. Scheduling strategy

See when threads are scheduled first and when they are scheduled later

Set the static priority and dynamic priority

Stack size and alert area size

4. Exit the processing routine

Thread small practice code

1, the use of named pipes to achieve two-way communication, can be sent messages to each other, using threads.

Example code jack:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#define FIFO_PATHNAME1 "/tmp/myfifo1"
#define FIFO_PATHNAME2 "/tmp/myfifo2"

int flag;

void *read_sig(void *arg)
{
	char r_buf[1024] = {0};
	while(1)
	{
		bzero(r_buf, sizeof(r_buf));
		read(*(int *)arg, r_buf, sizeof(r_buf));
		printf("rose:%s\n", r_buf);
		if (strcmp(r_buf, "quit") = =0)
		{
			kill(flag, 9);
			break; }}}int main(int argc, char const *argv[])
{
	flag = getpid();
	signal(9, SIG_DFL);
	// Create a named pipe (check if the file exists)
	if(access(FIFO_PATHNAME1, F_OK))	// Check whether the file exists
	{
		int ret = mkfifo(FIFO_PATHNAME1, 0644);
		if (ret == - 1)
		{
			perror("mkfifo FIFO_PATHNAME1");
			return - 1; }}if(access(FIFO_PATHNAME2, F_OK))	// Check whether the file exists
	{
		int ret = mkfifo(FIFO_PATHNAME2, 0644);
		if (ret == - 1)
		{
			perror("mkfifo FIFO_PATHNAME2");
			return - 1; }}// Open a named pipe
 	int fd1 = open(FIFO_PATHNAME1, O_RDWR);
 	if (fd1 == - 1)
 	{
 		perror("open");
		return - 1;
 	}

 	// Open a named pipe
 	int fd2 = open(FIFO_PATHNAME2, O_RDWR);
 	if (fd2 == - 1)
 	{
 		perror("open");
		return - 1;
 	}
 	printf("Named pipe opened successfully \n");

 	pthread_t pid;
 	pthread_create(&pid, NULL, read_sig, (void *)&fd1);

 	char w_buf[1024] = {0};
 	while(1)
 	{
 		/ / write data
 		bzero(w_buf, sizeof(w_buf)); 	
	 	scanf("%s", w_buf);

	 	write(fd2, w_buf, strlen(w_buf));
	 	if (strcmp(w_buf, "quit") = =0)
	 	{
	 		break; }}return 0;
}
Copy the code

rose:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#define FIFO_PATHNAME1 "/tmp/myfifo1"
#define FIFO_PATHNAME2 "/tmp/myfifo2"

int flag = 0;

void *read_sig(void *arg)
{
	char r_buf[1024] = {0};
	while(1)
	{
		bzero(r_buf, sizeof(r_buf));
		read(*(int *)arg, r_buf, sizeof(r_buf));
		printf("jack:%s\n", r_buf);
		if (strcmp(r_buf, "quit") = =0)
		{
			kill(flag, 9);
			break; }}}int main(int argc, char const *argv[])
{
	flag = getpid();
	signal(9, SIG_DFL);
	// Create a named pipe (check if the file exists)
	if(access(FIFO_PATHNAME1, F_OK))	// Check whether the file exists
	{
		int ret = mkfifo(FIFO_PATHNAME1, 0644);
		if (ret == - 1)
		{
			perror("mkfifo FIFO_PATHNAME1");
			return - 1; }}if(access(FIFO_PATHNAME2, F_OK))	// Check whether the file exists
	{
		int ret = mkfifo(FIFO_PATHNAME2, 0644);
		if (ret == - 1)
		{
			perror("mkfifo FIFO_PATHNAME2");
			return - 1; }}// Open a named pipe
 	int fd1 = open(FIFO_PATHNAME1, O_RDWR);
 	if (fd1 == - 1)
 	{
 		perror("open");
		return - 1;
 	}

 	// Open a named pipe
 	int fd2 = open(FIFO_PATHNAME2, O_RDWR);
 	if (fd2 == - 1)
 	{
 		perror("open");
		return - 1;
 	}
 	printf("Named pipe opened successfully \n");

 	pthread_t pid;
 	pthread_create(&pid, NULL, read_sig, (void *)&fd2);

 	char w_buf[1024] = {0};
 	while(1)
 	{
 		/ / write data
 		if (flag == 1)
 		{
 			break;
 		}
 		bzero(w_buf, sizeof(w_buf)); 	
	 	scanf("%s", w_buf);
	 	write(fd1, w_buf, strlen(w_buf));
	 	if (strcmp(w_buf, "quit") = =0)
	 	{
	 		break; }}return 0;
}
Copy the code

Running results:

2, the use of message queue to achieve two-way communication, you can send messages to each other, using threads.

Example code: Jack

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>

#define F1 1L
#define F2 2L

struct msgbuf
{
	long mtype; // Identifies the message
	char mtext[50]; // The message body
};

void *msg_recv(void *arg)
{
	struct msgbuf msg = {.mtype = F2};
	while(1)
	{
		msgrcv(*(int *)arg, &msg, sizeof(msg.mtext), F2, 0);
		printf("rose:%s\n", msg.mtext); }}int main(int argc, char const *argv[])
{
	// Get the key value
	key_t key = ftok(".".12);
	if (key == - 1)
	{
		perror("ftok");
		return - 1;
	}

	// Get the message queue ID
	int msgid = msgget(key,  IPC_CREAT | 0666);
	if (msgid == - 1)
	{
		perror("msgget");
		return - 1;
	}

	pthread_t pid;
	pthread_create(&pid, NULL, msg_recv, (void *)&msgid);

	// Send data
	// Define the send data structure variable
	struct msgbuf msg = {.mtype = F1};

	while(1)
	{
		scanf("%s", msg.mtext);
		msgsnd(msgid, &msg, strlen(msg.mtext)+1.0);
		if (strcmp(msg.mtext, "quit") = =0)
		{
			break; }}return 0;
}
Copy the code

rose

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>

#define F1 1L
#define F2 2L

struct msgbuf
{
	long mtype; // Identifies the message
	char mtext[50]; // The message body
};

void *msg_recv(void *arg)
{
	struct msgbuf msg = {.mtype = F1};
	while(1)
	{
		msgrcv(*(int *)arg, &msg, sizeof(msg.mtext), F1, 0);
		printf("jack:%s\n", msg.mtext); }}int main(int argc, char const *argv[])
{
	// Get the key value
	key_t key = ftok(".".12);
	if (key == - 1)
	{
		perror("ftok");
		return - 1;
	}

	// Get the message queue ID
	int msgid = msgget(key,  IPC_CREAT | 0666);
	if (msgid == - 1)
	{
		perror("msgget");
		return - 1;
	}

	pthread_t pid;
	pthread_create(&pid, NULL, msg_recv, (void *)&msgid);

	// Send data
	// Define the send data structure variable
	struct msgbuf msg = {.mtype = F2};

	while(1)
	{
		scanf("%s", msg.mtext);
		msgsnd(msgid, &msg, strlen(msg.mtext)+1.0);
		if (strcmp(msg.mtext, "quit") = =0)
		{
			break; }}return 0;
}
Copy the code

The results

3. The main thread opens A file and creates two threads, thread A writes A: thread 1 to the file every second, thread B writes A: thread 2 to the file every second. The main thread closes two threads after a minute

Requirement: Pass the file descriptor to the thread via a pass parameter.

The sample code

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>


void *func1(void *arg)
{
	char *p = "A: thread 1 \ r \ n";
	while(1)
	{
		sleep(1);
		write(*(int *)arg, p, strlen(p)); }}void *func2(void *arg)
{
	char *p = "B: thread 2 \ r \ n";
	while(1)
	{
		sleep(1);
		write(*(int *)arg, p, strlen(p)); }}void func3(int m)
{
	printf("3m = %d\n", m);
}

void func4(int m)
{
	printf("4m = %d\n", m);
}

int main(int argc, char const *argv[])
{

	int fd = open("test3.txt", O_RDWR);	

	void *p[2] = {func1, func2};

	// void (*p1[2])(int) = {func3, func4}; 

	pthread_t pid[2];
	for (int i = 0; i < 2; ++i)
	{
		pthread_create(&pid[i], NULL, p[i], (void *)&fd);
	}

	int i = 0;
	while(1)
	{
		i++;
		sleep(1);
		printf("i = %d\n", i);
		if (i == 10)
		{
			break; }}return 0;
}
Copy the code

The results