C pthread 不启动
C pthread doesn't start
我正在用 C 编写一个简单的报价服务器,运行正在 Linux 上编写。它应该从一个文本文件中随机选择一个引用,然后启动两个线程:
- 第一个负责接受传入连接并使用所选报价进行响应,
- 如果一天过去了,第二个应该每小时检查一次。如果它检测到新的一天已经开始,它应该随机选择另一个报价。
我的问题是,虽然连接线程工作正常,但另一个甚至没有启动。
为了确认这一点,我尝试在线程执行的函数的开头添加一个调试打印,另一个在它的 while 循环中并打印 none(这些已从显示的代码中删除在这里)。
我还添加了一些代码来检查从它的手册页复制的 pthread_create()
return 值,但我不确定它是否真的有效,因为它没有检测到任何错误。
我已经决定先启动 "timer thread" 并且根本不启动连接线程,但它仍然没有被执行。下面是相关代码,你可以在 GitHub:
上找到完整的源代码
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
pthread_mutex_t quoteLock=PTHREAD_MUTEX_INITIALIZER;
pthread_t checkForNewDayThread, connectionHandlerThread;
void * timer_thread_code(){ //The thread will act as a timer checking every hour if a day has passed
while (true) {
sleep(3600);
if (a_day_has_passed()) {
pthread_mutex_lock("eLock);
QOTD = read_random_quote_from_file(pathToQOTDfile);
pthread_mutex_unlock("eLock);
}
}
}
void * connection_thread_code(int port){ //Code for the thread to handle connections
struct sockaddr_in address;
int server_fd, new_socket, opt = 1, addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 1717
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))==-1)
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( port );
// Forcefully attaching socket to the port 1717
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 100) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("Listening on port %i\n", port);
while(1) { //connection handler loop
if ((new_socket = accept(server_fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
pthread_mutex_lock("eLock);
send(new_socket, QOTD, strlen(QOTD), 0);
pthread_mutex_unlock("eLock);
close(new_socket);
}
}
int main(int argc, char const *argv[])
{
int thread1, thread2, join;
thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);
if(thread1!=0) handle_error_en(thread1, "pthread_create");
thread2=pthread_create(&checkForNewDayThread, NULL, timer_thread_code(), NULL);
if(thread2!=0) handle_error_en(thread2, "pthread_create");
join=pthread_join(connectionHandlerThread, NULL);
if(join!=0) handle_error_en(join, "pthread_join");
return 0;
}
注意:我只放了一个 pthread_join()
因为两个线程都应该 运行 永远,所以为了防止 return 从 main 开始,只加入两个线程中的一个就足够了。
在此先感谢所有帮助过我的人
当您像在代码中那样调用 pthread_create
时:
thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);
您实际上首先在主线程上调用 connection_thread_code(port)
,并将该函数调用的 return 值作为参数传递给 pthread_create
。
那不是你想做的。您想要将函数指针作为参数传递给 pthread_create
,以及要传递给它的参数:
int port = 1234; /* <-- make sure this is in scope for the duration of the thread ! */
thread1 = pthread_create(&connectionHandlerThread, NULL, connection_thread_code, &port);
/* ... */
pthread_join(connectionHandlerThread, NULL);
为此,您的线程函数应具有以下签名:
void* connection_thread_code(void* port_ptr);
然后像这样获取端口:
int port = *((int*) port_ptr);
阅读更多有关将 int
参数传递给线程函数的信息 here。
与第二个线程类似(传递函数指针而不是调用函数,并更改签名)。
我正在用 C 编写一个简单的报价服务器,运行正在 Linux 上编写。它应该从一个文本文件中随机选择一个引用,然后启动两个线程:
- 第一个负责接受传入连接并使用所选报价进行响应,
- 如果一天过去了,第二个应该每小时检查一次。如果它检测到新的一天已经开始,它应该随机选择另一个报价。
我的问题是,虽然连接线程工作正常,但另一个甚至没有启动。
为了确认这一点,我尝试在线程执行的函数的开头添加一个调试打印,另一个在它的 while 循环中并打印 none(这些已从显示的代码中删除在这里)。
我还添加了一些代码来检查从它的手册页复制的 pthread_create()
return 值,但我不确定它是否真的有效,因为它没有检测到任何错误。
我已经决定先启动 "timer thread" 并且根本不启动连接线程,但它仍然没有被执行。下面是相关代码,你可以在 GitHub:
上找到完整的源代码#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
pthread_mutex_t quoteLock=PTHREAD_MUTEX_INITIALIZER;
pthread_t checkForNewDayThread, connectionHandlerThread;
void * timer_thread_code(){ //The thread will act as a timer checking every hour if a day has passed
while (true) {
sleep(3600);
if (a_day_has_passed()) {
pthread_mutex_lock("eLock);
QOTD = read_random_quote_from_file(pathToQOTDfile);
pthread_mutex_unlock("eLock);
}
}
}
void * connection_thread_code(int port){ //Code for the thread to handle connections
struct sockaddr_in address;
int server_fd, new_socket, opt = 1, addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 1717
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))==-1)
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( port );
// Forcefully attaching socket to the port 1717
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 100) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
printf("Listening on port %i\n", port);
while(1) { //connection handler loop
if ((new_socket = accept(server_fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
pthread_mutex_lock("eLock);
send(new_socket, QOTD, strlen(QOTD), 0);
pthread_mutex_unlock("eLock);
close(new_socket);
}
}
int main(int argc, char const *argv[])
{
int thread1, thread2, join;
thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);
if(thread1!=0) handle_error_en(thread1, "pthread_create");
thread2=pthread_create(&checkForNewDayThread, NULL, timer_thread_code(), NULL);
if(thread2!=0) handle_error_en(thread2, "pthread_create");
join=pthread_join(connectionHandlerThread, NULL);
if(join!=0) handle_error_en(join, "pthread_join");
return 0;
}
注意:我只放了一个 pthread_join()
因为两个线程都应该 运行 永远,所以为了防止 return 从 main 开始,只加入两个线程中的一个就足够了。
在此先感谢所有帮助过我的人
当您像在代码中那样调用 pthread_create
时:
thread1=pthread_create(&connectionHandlerThread, NULL, connection_thread_code(port), NULL);
您实际上首先在主线程上调用 connection_thread_code(port)
,并将该函数调用的 return 值作为参数传递给 pthread_create
。
那不是你想做的。您想要将函数指针作为参数传递给 pthread_create
,以及要传递给它的参数:
int port = 1234; /* <-- make sure this is in scope for the duration of the thread ! */
thread1 = pthread_create(&connectionHandlerThread, NULL, connection_thread_code, &port);
/* ... */
pthread_join(connectionHandlerThread, NULL);
为此,您的线程函数应具有以下签名:
void* connection_thread_code(void* port_ptr);
然后像这样获取端口:
int port = *((int*) port_ptr);
阅读更多有关将 int
参数传递给线程函数的信息 here。
与第二个线程类似(传递函数指针而不是调用函数,并更改签名)。