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