总结这一段时间做te项目时遇到的小问题。
一、alarm(), signal()函数
alarm()函数
头文件: #include
原型:unsigned int alarm(unsigned int seconds);
功能:经过seconds秒后,向目前的进程发送SIGALARM信号
返回值:若调用多个alarm函数,则第二个alarm将取代第一个,并返回第一个alarm的生于时间。
详见:https://typecodes.com/linux/linuxalarmknockfunc.html
signal()函数
头文件:#include
原型:sighandler_t signal(int signum, sighandler_t handler);
功能:截取signum信号,截取成功后执行handler指向的函数
handler是一个函数指针,指向一个void sig_handle(int signo)函数,用户在sig_handle函数中定义所需动作。
handler也可以是 SIG_IGN和SIG_DFL。
SIG_IGN表示屏蔽该信号;
SIG_DFL表示恢复该信号的默认设置。
另:handler函数应该为静态函数。
二、c++静态成员函数
c++中,类的静态成员属于类,而不属于某个对象,因此可以通过静态成员在同一类的对象中共享数据。
静态成员函数的声明(.h文件):
class example
{
public:
static void handle(int signo);
};
静态成员函数的实现(.cpp文件):
void examp::handle(int signo)//不用加static
{
......
}
静态成员函数的引用:
1.像其他成员函数一样
对象::handler(..);
2.直接通过类名引用
example::handler(...);
三、fcntl()函数
头文件:#include
#include
#include
原型:int fcntl(int fd, int cmd, ...);
功能:改变文件描述符的属性
如:
//将服务器端口设为非阻塞
fcntl(server_sockfd, F_SETFL, fcntl(server_sockfd, F_GETFL, 0)|O_NONBLOCK);
详见:https://blog.csdn.net/bailyzheng/article/details/7463775
三、linux线程编程
同一个进程中的所有线程共享资源。
线程的创建和结束
1.pthread_create()
int pthread_create(
pthread_t *thread,
pthread_attr_t *attr,
void* (*static_routine)(void *),
void *arg);
thread:线程的标识
attr:线程的属性,设为NULL表示默认属性
start_routine:线程中运行的单元,用户自己编写
arg:线程函数运行时传入的参数
线程创建成功返回0,失败返回非0值。
在c++里,类中需要调用pthread_creat函数时,static_routine应为是静态函数的指针,可采用以下方法:
#include
#include
#include
int Exa::create()
{
pthread_t pt;
ret=pthread_create(&pt,NULL,thread,(void*)this);//this为指向本对象的指针
}
void* Exa::thread(void *tmp)
{
Exa *p=(Exa*)tmp;
p->my_thread();
}
void Exa::my_thread()
{
printf("hey\n");
}
2.pthread_join()和pthread_exit()
函数pthread_join()为阻塞函数,用于等待一个线程运行结束。线程返回时,函数才会返回并且收回线程资源。
int pthread_join(
pthread_t __th,
void **__thread_return
);
__th:为线程标识符,即pthread_create()函数创建成功的值
__thread_return:指针,用于存储线程返回值
例如:
Exa::return()
{
pthread_join(pt,NULL);
}
pthread_exit(),线程主动调用此函数退出。
void pthread_exit(void* ret);
ret:指针,指向线程退出的时候需要返回的值
线程互斥
由于同一进程中的所有线程共用资源,为防止两个线程使用资源时产生冲突,因此需要使用线程互斥锁。
初始化互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
mutex: 互斥锁变量
mutexattr:互斥锁属性,设为NULL,表示默认属性
锁定互斥
int pthread_mutex_lock(pthread_mutex_t *mutex);
解锁互斥
int pthread_mutex_unlock(pthread_mutex_t *mutex);
销毁互斥
int pthread_mutex_destroy(pthread_mutex_t *mutex);
例如:
void Exa::my_thread()
{
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);
pthread_mutex_lock(&mutex);
a=3;
pthread_mutex_unlock(&mutex);
}
编译
由于pthread.h不是Linux的标准库,在使用G++编译时,要在最后加-lpthread参数
四、select()函数
select函数可以对文件描述符进行查询,查看文件描述符是否可进行读写操作。
#include
#include
#include
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set *exceptfds, struct timeval *timeout);
nfds:监视的文件描述符集中,最大的文件描述符+1
readfds:监视该文件描述符集中的文件是否可以进行读操作
writefds:监视该文件描述符集中的文件是否可以进行写操作
exceptfds:监视该文件描述符集中是否有文件描述符发生错误,也可用于其他的用途
timeout:最长等待时间
有符合条件的事件发生时,返回值大于0;当超时时,返回0;发生错误时,返回-1,错误值存于errno。
操作文件描述符的宏:
FD_ZERO():将文件描述符集置为空
FD_SET():向某个文件描述符集中加入文件描述符
FD_CLR():向某个文件描述符集中去除文件描述符
FD_ISSET():测试某个文件描述符集中是否含有某个文件描述符
例如:
#include
#include
#include
#include
int main()
{
fd_set rdfd;
struct timeval tv;
int err;
FD_ZERO(rdfd);
FD_SET(0,&rdfd);
tv.tv_sec=5;//设置等待时间为5秒
tv.tv_usec=0;
err=select(1,&rdfd,NULL,NULL,&tv);
if(err==-1)
{
printf("select error\n");
return -1;
}
else if(err==0)
{
printf("timed out\n");
return -1;
}
else
{
printf("data available\n");
return 0;
}
注:调用select()函数后,结构体timeval的值会替换为剩余时间;如果文件描述符集中的某个文件描述符在超时前发生变化(可读\可写),该文件描述符在集中的位置会被置零,因此如果需要循环调用select()函数监控某一个文件描述符,每次调用select()函数之前都要重新初始化等待时间,并将需要监控的文件描述符加入文件描述符集。
五、pthread_cond_timedwait()函数
当sleep()延时不准确,不方便使用alarm()计时的时候,可以单独开始一个线程,使用pthread_cond_timedwait()进行计时。
int pthread_cond_init(
pthread_cond_t *cv,
const pthread_condattr_t *cattr);
cv:一个条件变量
cattr:属性,设为NULL为默认属性
int pthread_cond_timedwait(
pthread_cond_t __cond,
pthread_mutex_t __mutex,
struct timespec __abstime
);
__cond:条件变量
__mutex:互斥锁
__adstime:等待时间
pthread_cond_timedwait()需要配合互斥锁使用,例如
void main()
{
pthread_t thread1;
pthread_t thread2;
pthread_mutex_t mutex;
pthread_cond_t m_cond;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&m_cond,NULL);
pthread_create(&thread1,NULL,thread1,NULL);
pthread_create(&thread2,NULL,thread2,NULL);
usleep(1);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
exit(0);
}
static void* thread1()
{
pthread_mutex_lock(&mutex);
gettimeofday(&now,NULL);
m_time.tv_sec=now.tv_sec+10;
m_time.tv_nsec=now.tv_usec*1000;
ret=pthread_cond_timedwait(&m_cond,&mutex,&m_time);
pthread_mutex_unlock(&mutex);
}
static void* thread2()
{
pthread_mutex_lock(&mutex);
gettimeofday(&now,NULL);
m_time.tv_sec=now.tv_sec+10;
m_time.tv_nsec=now.tv_usec*1000;
ret=pthread_cond_timedwait(&m_cond,&mutex,&m_time);
pthread_mutex_unlock(&mutex);
}