1、kill
NAME
kill - send signal to a process
SYNOPSIS
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
RETURN VALUE
On success (at least one signal was sent), zero is returned. On error, -1 is returned, and errno is set appropriately.
使用:
int main(int argc, char *argv[])
{
int i = 0;
pid_t pid = atoi(argv[1]);
while (1)
{
printf("this is %dth while\n", i+1);
sleep(1);
i++;
if (5 == i)
{
printf("kill other process\n");
kill(pid, SIGKILL);
}
}
return 0;
}
2、raise 发送一个信号给进程本身(完全可以用kill代替)
NAME
raise - send a signal to the caller
SYNOPSIS
#include <signal.h>
int raise(int sig);
3、alarm 定时发送信号 ,结束程序 //SIGALRM 不可以设多个,后面的会替代前面的
NAME
alarm - set an alarm clock for delivery of a signal
SYNOPSIS
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
RETURN VALUE
alarm() returns the number of seconds remaining until any previously scheduled alarm was due to be delivered, or zero if there was
no previously scheduled alarm.
使用:
int main(void)
{
alarm(5);
//SIGALRM:结束程序
alarm(2);
//会将之前的闹钟取消
while (1)
{
printf("aaaaaaa\n");
sleep(1);
}
return 0;
}
1、设置信号处理动作:singal
NAME
signal - ANSI C signal handling
SYNOPSIS
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t
signal(int signum, sighandler_t handler);
RETURN VALUE
signal() returns the previous value of the signal handler, or SIG_ERR on error. In the event of an error, errno is set to indicate
the cause.
使用:
void handle(int sig)
{
if (SIGINT == sig)
{
printf("catched sigint\n");
}
}
int main(void)
{
//ctrl+c: SIGINT
//设置信号的处理动作
signal(SIGINT, handle);
while (1)
{
printf("this is main while\n");
sleep(1);
}
return 0;
}
2、屏蔽信号
(1)将信号添加到信号组: sigemptyset sigaddset
NAMEdfsigemptyset, sigfillset, sigaddset, sigdelset, sigismember - POSIX signal set operations
SYNOPSIS
#include <signal.h>
int sigemptyset(sigset_t *set); //清空信号集合
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum); //添加信号到集合中
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
DESCRIPTION
These functions allow the manipulation of POSIX signal sets.
sigemptyset() initializes the signal set given by set to empty, with all signals excluded from the set.
sigfillset() initializes set to full, including all signals.
sigaddset() and sigdelset() add and delete respectively signal signum from set.
sigismember() tests whether signum is a member of set.
Objects of type sigset_t must be initialized by a call to either sigemptyset() or sigfillset() before being passed to the functions
sigaddset(), sigdelset() and sigismember() or the additional glibc functions described below (sigisemptyset(), sigandset(), and
sigorset()). The results are undefined if this is not done.
RETURN VALUE
sigemptyset(), sigfillset(), sigaddset(), and sigdelset() return 0 on success and -1 on error.
sigismember() returns 1 if signum is a member of set, 0 if signum is not a member, and -1 on error.
On error, these functions set errno to indicate the cause of the error.
(2)对信号组进行设置:sigprocmask
NAME
sigprocmask, rt_sigprocmask - examine and change blocked signals
SYNOPSIS
#include <signal.h>
参数2:
sigset_t 结构体,信号集合, 将需要的信号添加到其中即可
int sigprocmask(
int how,
const sigset_t *set,
sigset_t *oldset); 参数3:信号之前的状态
SIG_BLOCK (阻塞) 也就是上面的参数1:how
The set of blocked signals is the union of the current set and the set argument.
SIG_UNBLOCK (解阻塞)
The signals in set are removed from the current set of blocked signals. It is permissible to attempt to unblock a signal
which is not blocked.
SIG_SETMASK
The set of blocked signals is set to the argument set.
RETURN VALUE
sigprocmask() returns 0 on success and -1 on error. In the event of an error, errno is set to indicate the cause.
使用:
sigset_t set;
void handle(int sig)
{
//ctrl+c
if (SIGINT == sig)
{
#if 0
//若信号阻塞的操作是在信号的处理函数中进行的
//则函数结束后,阻塞无效
sigset_t set;
//清空信号集合
sigemptyset(&set);
//添加SIGTSTP到集合中
sigaddset(&set, SIGTSTP);
//SIG_BLOCK:将信号集合中的信号阻塞
//参数三:用来保存参数二中的信号之前的状态
//NULL表示不保存之前的状态
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
printf("$$$$$$$$$$$$$$$$\n");
int i = 0;
while (1)
{
printf("this is SIGINT handle\n");
sleep(1);
i++;
if (5 == i)
{
break;
}
}
//若有一个信号被阻塞但是多次发生
//则解阻塞之后该信号只会被处理一次
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
else if (SIGTSTP == sig)
{
//ctrl+z
printf("this is SIGTSTP handle\n");
}
}
int main(void)
{
// sigset_t set;
//清空信号集合
sigemptyset(&set);
//添加SIGTSTP到集合中
sigaddset(&set, SIGTSTP);
//SIG_BLOCK:将信号集合中的信号阻塞
//参数三:用来保存参数二中的信号之前的状态
//NULL表示不保存之前的状态
sigprocmask(SIG_BLOCK, &set, NULL);
signal(SIGINT, handle);
signal(SIGTSTP, handle);
while (1)
{
printf("this is main while \n");
sleep(1);
}
return 0;
}
3、一个函数完成上面上面两个功能:sigaction
NAME
sigaction, rt_sigaction - examine and change a signal action
SYNOPSIS
#include <signal.h>
int sigaction(
int signum
,
const struct sigaction *act
,
参数1:要处理的信号
参数2:通过结构体对信号进行
struct sigaction *oldact); 参数
3:保留之前的处理方式,不想保留设置为:NULL
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //信号集合,
int sa_flags; //配置
void (*sa_restorer)(void);
};
SA_NOCLDSTOP
flags: 若信号是SIGCHLD,处理过程中不处理其他信号
If signum is SIGCHLD, do not receive notification when child processes stop (i.e., when they receive one of SIGSTOP,
SIGTSTP, SIGTTIN, or SIGTTOU) or resume (i.e., they receive SIGCONT) (see wait(2)). This flag is meaningful only when
establishing a handler for SIGCHLD.
SA_NOCLDWAIT (since Linux 2.6)
If signum is SIGCHLD, do not transform children into zombies when they terminate. See also waitpid(2). This flag is
meaningful only when establishing a handler for SIGCHLD, or when setting that signal's disposition to SIG_DFL.
If the SA_NOCLDWAIT flag is set when establishing a handler for SIGCHLD, POSIX.1 leaves it unspecified whether a SIGCHLD
signal is generated when a child process terminates. On Linux, a SIGCHLD signal is generated in this case; on some
other implementations, it is not.
SA_NODEFER //处理A A再次发生 不阻塞A
Do not prevent the signal from being received from within its own signal handler. This flag is meaningful only when
establishing a signal handler. SA_NOMASK is an obsolete, nonstandard synonym for this flag.
SA_ONSTACK
Call the signal handler on an alternate signal stack provided by sigaltstack(2). If an alternate stack is not avail‐
able, the default stack will be used. This flag is meaningful only when establishing a signal handler.
SA_RESETHAND //当信号发生时调用特殊函数处理,处理完按默认方式处理,仅执行一次
Restore the signal action to the default upon entry to the signal handler. This flag is meaningful only when establish‐
ing a signal handler. SA_ONESHOT is an obsolete, nonstandard synonym for this flag.
SA_RESTART
Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals. This
flag is meaningful only when establishing a signal handler. See signal(7) for a discussion of system call restarting.
SA_RESTORER
Not intended for application use. This flag is used by C libraries to indicate that the sa_restorer field contains the
address of a "signal trampoline". See sigreturn(2) for more details.
SA_SIGINFO (since Linux 2.2)
The signal handler takes three arguments, not one. In this case, sa_sigaction should be set instead of sa_handler.
This flag is meaningful only when establishing a signal handler.
RETURN VALUE
sigaction() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.
使用:
void handle(int sig)
{
if (SIGINT == sig)
{
printf("$$$$$$$$$$$$$$$$\n");
int i = 0;
while (1)
{
printf("this is SIGINT handle\n");
sleep(1);
i++;
if (5 == i)
{
break;
}
}
}
else if (SIGTSTP == sig)
{
//ctrl+z
printf("this is SIGTSTP handle\n");
}
}
int main(void)
{
struct sigaction act;
act.sa_handler = handle;
sigemptyset(&(act.sa_mask));
sigaddset(&(act.sa_mask), SIGTSTP);
//通过结构体同时设置某个信号的处理函数和需要屏蔽的信号集
sigaction(SIGINT, &act, NULL);
struct sigaction act2;
act2.sa_handler = handle;
sigaction(SIGTSTP, &act2, NULL);
while (1)
{
printf("this is main while \n");
sleep(1);
}
return 0;
}
1、信号的创建:sem_init (一般用于线程同步)
NAME
sem_init - initialize an unnamed semaphore
SYNOPSIS
#include <semaphore.h>
参数1:要初始化的信号量 2:设置该信号量用于
int sem_init(
sem_t *sem
,
int pshared
,
unsigned int value);
//
初始化信号量
参数1:要初始化的信号量
Link with -pthread. //
参数2:设置该信号量用于进程间同步还是用于线程间同步 //0:表示用于线程间 //非0:表示用于进程间
RETURN VALUE //
参数3:信号量的整数值,代表资源的可用数
sem_init()
returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.
2、信号的等待:sem_wait
NAME
sem_wait, sem_timedwait, sem_trywait - lock a semaphore
SYNOPSIS
#include <semaphore.h>
int sem_wait(sem_t *sem); //等于0等待
int sem_trywait(sem_t *sem); //等于0不等待,去做其他事
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); //等于0,等待指定之间,然后去做其他事
3、通知等待某信号的线程:sem_post 将信号量加1
NAME
sem_post - unlock a semaphore
SYNOPSIS
#include <semaphore.h>
int sem_post(sem_t *sem);
Link with -pthread.
RETURN VALUE
sem_post() returns 0 on success; on error, the value of the semaphore is left unchanged, -1 is returned, and errno is set to indi‐
cate the error.
1、信号量的创建semget
//创建信号量集合
//参数一:使用一个十六进制的整数作为该集合的名字
// 名字可以重复
//参数二: 设置该集合中信号量的个数
//IPC_CREAT|0664:创建集合并指定操作权限
//成功返回该集合的标识符,
//通过标识符来唯一确定集合
semid =
semget(0x1024, NUM, IPC_CREAT|0664);
2、对信号量的设定
semop
1)创建信号集 semid = semget。。
semid = semget(0x1024, NUM, IPC_CREAT|0664);
2)定义结构体 struct sembuf sem
int left = num;
int right = (num+1)%NUM;
struct sembuf sem[2] = {{left, -1, 0}
, {right, -1, 0}};
3)
//通过结构体指定的操作来操作集合中的信号量
semop(semid, sem, 2);
参数1:信号集标识符,
参数2:
sops:指向进行操作的信号量集结构体数组的首地址,此结构的具体说明如下:
struct sembuf {
short semnum; /*信号量集合中的信号量编号,0代表第1个信号量*/
short val;/*若val>0进行V操作信号量值加val,表示进程释放控制的资源 */
/*若val<0进行P操作信号量值减val,若(semval-val)<0(semval为该信号量值),则调用进程阻塞,直到资源可用;若设置IPC_NOWAIT不会睡眠,进程直接返回EAGAIN错误*/
/*若val==0时阻塞等待信号量为0,调用进程进入睡眠状态,直到信号值为0;若设置IPC_NOWAIT,进程不会睡眠,直接返回EAGAIN错误*/
short flag; /*0 设置信号量的默认操作*/
/*IPC_NOWAIT设置信号量操作不等待*/
/*SEM_UNDO 选项会让内核记录一个与调用进程相关的UNDO记录,如果该进程崩溃,则根据这个进程的UNDO记录自动恢复相应信号量的计数值*/
};
|
参数3:进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作
返回:信号集标识符
3、设置集合中信号量的值:semctl
//参数一:集合标识符
//参数二:集合中第几个信号量
//参数三:对集合的操作命令
// SETVAL:对信号量赋值
//参数四:根据命令传入不定个数的数据
semctl(semid, i, SETVAL, sem);
1) semid = semget(0x1024, NUM, IPC_CREAT|0664);
2)定义联合体 union semun sem
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
union semun sem;
sem.val = 1;
3)设置集合中信号量的值:semctl
semctl(semid, i, SETVAL, sem);
使用:
pthread_mutex_t pmutex;
pthread_mutex_t gmutex;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
#define NUM 5//用来保存信号量集合的标识符
int semid = -1;//获得筷子
void getChopsticks(int num)
{
int left = num;
int right = (num+1)%NUM;
//成员一:操作集合中第几个信号量
//成员二:-1表示获得资源,1表示释放资源
//成员三:0表示若资源不满足则阻塞等待直到满足为止
struct sembuf sem[2] = {{left, -1, 0}
, {right, -1, 0}};
//通过结构体指定的操作来操作集合中的信号量
semop(semid, sem, 2);
}
//放下筷子
void putChopsticks(int num)
{
int left = num;
int right = (num+1)%NUM;
//成员一:操作集合中第几个信号量
//成员二:-1表示获得资源,1表示释放资源
//成员三:0表示若资源不满足则阻塞等待直到满足为止
struct sembuf sem[2] = {{left, 1, 0}
, {right, 1, 0}};
//通过结构体指定的操作来操作集合中的信号量
semop(semid, sem, 2);
}
void *run(void *arg)
{
int num = (int)arg;
while (1)
{
printf("第%d个哲学家正在思考...\n", num+1);
sleep(1);
//获得筷子吃饭
pthread_mutex_lock(&gmutex);
getChopsticks(num);
printf("第%d个哲学家获得筷子吃饭...\n", num+1);
pthread_mutex_unlock(&gmutex);
sleep(1);
pthread_mutex_lock(&pmutex);
putChopsticks(num);
printf("第%d个哲学家放下筷子...\n", num+1);
pthread_mutex_unlock(&pmutex);
sleep(1);
}
}
int main(void)
{
int i = 0;
//创建信号量集合
//参数一:使用一个十六进制的整数作为该集合的名字
// 名字可以重复
//参数二: 设置该集合中信号量的个数
//IPC_CREAT|0664:创建集合并指定操作权限
//成功返回该集合的标识符,
//通过标识符来唯一确定集合
semid = semget(0x1024, NUM, IPC_CREAT|0664);
union semun sem;
sem.val = 1;
for (i = 0; i < NUM; i++)
{
//设置集合中信号量的值
//参数一:集合标识符
//参数二:集合中第几个信号量
//参数三:对集合的操作命令
// SETVAL:对信号量赋值
//参数四:根据命令传入不定个数的数据
semctl(semid, i, SETVAL, sem);
}
pthread_t thr[NUM];
//创建五个哲学家线程
for (i=0; i<NUM; i++)
{
pthread_create(thr+i, NULL, run, (void*)i);
}
//等待线程结束
for (i=0; i<NUM; i++)
{
pthread_join(thr[i], NULL);
}
return 0;
}