1. 父子进程间的无名管道通信
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
int main()
{
int pfd[2];
int re;
char buf[20]={0};
pid_t pid;
//1. 创建管道
re = pipe(pfd);
if(re<0)
{
perror("pipe");
return 0;
}
printf("%d,%d\n",pfd[0],pfd[1]);
signal(SIGPIPE, myexit);
//2. 创建子进程
pid = fork();
if(pid<0)
{
perror("fork");
return 0;
}
else if(pid>0)
{
//3. 读进程,先关闭读管道
close(pfd[0]);
while(1)
{
strcpy(buf,"hhahahahah");
//4. 读进程写管道
write(pfd[1],buf,strlen(buf));
//close(pfd[1]);
sleep(1);
}
}
else
{
//5.子进程,先关闭写管道
close(pfd[1]);
while(1)
{
//6. 子进程,读进程
re=read(pfd[0],buf,20);
if(re>0)
{
printf("read pipe=%s\n",buf);
}
}
}
}
2. 独立进程之间的有名管道通信
注意:
当写入的时候,读端可能已经关闭/crash了,所以写端应该处理SIGPIPE信号
当读取的时候,写端可能已经关闭/crash了,此时读端read返回值为0
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
void myexit()
{
perror("has detected epip");
}
int main()
{
int re;
int fd;
char buf[32];
// 创建管道,注意路径
re = mkfifo("./myfifo",0666);
if(re<0)
{
perror("mkfifo");
//return 0;
}
// 打开写管道
fd = open("./myfifo",O_WRONLY);
if(fd<0)
{
perror("open");
return 0;
}
printf("after open\n");
// 为了避免在写管道的时候,读端已经关闭了的case,处理SIGPIPE信号,
// 这样写进程就不会直接退出,读进程重启之后,写进程可以继续正常写入
signal(SIGPIPE, myexit);
while(1)
{
fgets(buf,32,stdin);
write(fd,buf,strlen(buf));
}
}
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int re;
int fd;
char buf[32];
// 以只读方式,打开有名管道
fd = open("./myfifo",O_RDONLY);
if(fd<0)
{
perror("open");
return 0;
}
printf("after open\n");
while(1)
{
//读管道
re=read(fd,buf,32);
if(re>0)
{
printf("read fifo=%s\n",buf);
}
else if(re==0)
{
close(fd);
break;
}
}
}
3. fork创建子进程 处理僵尸进程
注意:
1) 当kill子进程的时候,WIFSTOPPED(status)会返回true,子进程就不会变成僵尸进程;
2) 父进程会轮询while(!WTERMSIG(status) && !WIFSTOPPED(status));
3) WIFEXITED(status)在子进程正常运行的时候,都会返回true
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
void myexit()
{
perror("111111");
exit(0);
}
int main()
{
int status =0;
signal(SIGINT, myexit);
signal(SIGTERM, myexit);
pid_t child = fork();
int i=100;
if(child)
{
printf("parent \n");
do{
pid_t p = waitpid(-1, &status, WNOHANG|WSTOPPED|WUNTRACED);
if(p<0)
{
perror("11111111");
return 0;
}
if(WIFEXITED(status))
{
printf("22222 exit:%d\n",status);
}
if(WIFSTOPPED(status))//WIFSTOPPED
{
perror("stop");
}
if(WTERMSIG(status))
{
// 当kill 子进程的时候,会走到这个case
perror("wait for term");
}
}while(!WTERMSIG(status) && !WIFSTOPPED(status));
}
else
{
printf("child\n");
// exit(1);
while(1){} // 故意让子进程不要退出
}
while(1){
}
return 0;
}
4. select监听控制台输入
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
while(1){
FD_ZERO(&rfds);
FD_SET(0,&rfds);
tv.tv_sec =5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
{
char buf[256]={0};
read(0, buf, sizeof(buf));
/* FD_ISSET(0, &rfds) will be true. */
printf("Data is available now.%s\n", buf);
}else
printf("No data within five seconds.\n");
}
exit(EXIT_SUCCESS);
}