pipe
无名管道,只能用于亲缘关系的进程间通信,半双工,固定读fd[0],写fd[1],文件I/O实现;
当管道中无数据时,读阻塞;
当写缓冲区满时又不被读走,此时写阻塞;
实例:父进程读阻塞,子进程写成功然后父进程读成功返回。
#include
#include
#include
#include
#define MAX 1024
int main()
{
int fd[2];
int ret = pipe(fd);
if(0 > ret)
{
perror("pipe");
exit(-1);
}
pid_t pid = fork();
if(0 > pid)
{
perror("fork");
exit(-1);
}
if(0 == pid)
{
printf("child process\n");
sleep(3);
char buf[] = "hello world";
ret = write(fd[1], buf, sizeof(buf)-1);
if(0 > ret)
{
perror("write");
exit(-1);
}
}
if(0 < pid)
{
char rbuf[MAX];
memset(rbuf, 0, MAX);
printf("parent process\n");
ret = read(fd[0], rbuf, MAX);
if(0 > ret)
{
perror("read");
exit(-1);
}
printf("read num:%d,buf:%s\n", ret, rbuf);
}
exit(0);
}
fifo
有名管道,可实现不相干的进程间通信,文件I/O操作。
读写阻塞通过O_NONBLOCK控制,表示非阻塞,下面例子是写非阻塞,读阻塞;先运行读进程(被阻塞),再运行写进程,一切正常;若先运行写进程,open调用将返回-1,打开失败。
#define FIFONAME "/tmp/myfifo"
mkfifo(FIFONAME, O_CREAT)
int fd = open(FIFONAME, O_WRONLY|O_NONBLOCK, 0);
char buf[] = "hello FIFO test.";
write(fd, buf, sizeof(buf)
char buf_r[100];
memset(buf_r,0,sizeof(buf_r));
int fd = open(FIFONAME, O_RDONLY, 0);
read(fd,buf_r, 100)
unlink(FIFONAME)
信号通信 kill/raise
中断控制,异步通信方式,软中断内核控制;
kill把信号发送给进程或进程组;int kill(pid_t pid, int signo);成功则返回0, 出错则返回-1;
raise把信号发送给(进程)自身;int raise(int signo);成功则返回0, 出错则返回-1。
kill(getppid(), SIGKILL);杀死父进程;
raise(SIGKILL);杀死自己进程;
wait函数
wait函数阻塞自己进程,直到自己的某一个子进程退出函数才返回;
pid_t wait(int *status),status保存子进程退出时的一些状态,返回子进程的id,
pid_t waitpid(pid_t pid, int *status, int options),pid>0时,只等待进程ID等于pid的子进程;pid=-1时,等待任何一个子进程退出;pid=0时,等待同一个进程组中的任何子进程;pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
alarm函数
alarm函数设置一个定时器,时间到后向当前进程发送一个SIGALARM终止信号;如果alarm()前已经设置了一个闹钟,可以调用alarm(0)来取消此闹钟,并返回剩余时间;如果想重新设置一个闹钟,可以alarm(n),会取消前的闹钟并返回剩余时间,然后重新开始倒计时。
pause函数
pause函数使进程或线程进入睡眠状态,直到收到信号。
signal函数
注册信号处理函数,函数原型:sighandler_t signal(int signum, sighandler_t handler);
signum是我们要处理的信号,系统信号可通过命令kill -l查看:
handler是收到信号后的处理动作,SIG_ING是收到信号后忽略,比如signal(SIGINT, SIG_IGN);收到中断信号忽略,那么用Ctrl+C就不能中断程序,此时可用Ctrl+\发送Quit信号;
handler还可以是函数,收到信号后执行函数,如下面的例子:收到信号后就去执行handler函数,执行完后前面的函数继续执行。
#include
#include
#include
#define _GNU_SOURCE
#define MAX 9
char arr[MAX];
void unrecall(int val)
{
for(int i = 0; i < MAX; i++)
{
arr[i] = val+i;
printf("NO %d.%d: %d\n",val, i, arr[i]);
sleep(1);
}
}
void handler(int sig)
{
unrecall(sig);
}
int main()
{
if(SIG_ERR == signal(SIGUSR1, handler))
perror("signal");
pid_t pid = fork();
if(0 > pid)
{
perror("fork");
exit(-1);
}
else if(0 == pid)
{
sleep(5);
kill(getppid(), SIGUSR1);
}
else if(0 < pid)
{
printf("SIGUSR1=%d\n", SIGUSR1);//10
unrecall(1);
for(int i = 0; i < MAX; i++)
{
printf("all:NO.%d: %d\n", i, arr[i]);
}
}
exit(0);
}
发送信号可用kill和raise函数。