linux IO系列:管道通信/阻塞非阻塞

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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值