linux进程间通讯--pipe(),fifo()

一 线程回收

   pthread_join(): 阻塞等待线程退出,并获取线程退出状态。   对应于进程中的waitpid()函数。

   int pthread_join(pthread_t thread, void **retval);  成功返回 0; 失败返回错误号。

    thread:线程id ; retval:保存线程退出状态

   进程中,main返回值,exit参数------>int;  pthread_exit---->void*; 等待子进程结束wait函数参数---->int *.

    线程中:线程主函数返回值,pthread_exit()---->void* ,等待线程结束pthread_join函数参数--->void ** .

 

调用此函数的线程会阻塞挂起等待,直到id为thread的线程终止,thread线程以不同的方法终止,通过pthread_join获取终止状态。

1、如果thread线程通过return返回。retval所指向的单元里存放的是thread线程函数的返回值。

2、如果thread线程被别的线程调用屏【thread_cancel()异常终止掉,retval所指向的单元里存放的常数PTHREAD_CANCELED

3、如果thread线程自己调用pthread_exit()终止,retval所指向的单元存放的是串改pthread_exit()的参数。

4、如果对thread线程的终止状态不感兴趣,可以传NULL给retval参数。

**************************************线程正常返回************************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <pthread.h>

typedef struct
{
int a;
int b;
}exit_t;

void *thread_func(void *arg)
{
exit_t *ret;
ret = (exit_t*)malloc(sizeof(exit_t));
ret->a = 100;
ret->b = 99;

pthread_exit((void*)ret);
}

int main(int argc,char *argv[])
{
exit_t *retval; //必须是指针
pthread_t tid;

int ret = pthread_create(&tid,NULL,&thread_func,NULL);
if(ret)
{
printf("Thread create failed.\n");
exit(1);
}

pthread_join(tid,(void**)&retval);  //参数必须取地址

printf("a = %d,b = %d \n",retval->a,retval->b);
free(retval);

pthread_exit(NULL);
}

***********************************************************************************

执行结果:

 

 

以上是回收一个线程,那么如果创建了多个子线程,又该如何去回收呢?

往往我们在实际项目应用中并不确定会使用多少个线程,这也就无法确定for循环的次数。对于这种情况,大牛们依旧为我们提供了很好的方式进行处理一遍回收线程。

二 线程分离 pthread_detach()

int pthread_detach(pthread_t thread); 成功返回0; 失败返回 -1,并设置错误号errno

线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后,其退出的状态不由其它线程获取,而有其自己自动释放。网络,多线程服务器常用。

  也可以使用pthread_create()的第二个参数类设置线程分离。

  进程如果有此机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资源仍在系统中,导致内核仍然认为该进程存在。

***************************************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <pthread.h>

typedef struct
{
int a;
int b;
}exit_t;

void *thread_func(void *arg)
{
exit_t *ret;
ret = (exit_t*)malloc(sizeof(exit_t));
ret->a = 100;
ret->b = 99;

pthread_exit((void*)ret);
}

int main(int argc,char *argv[])
{
exit_t *retval;
pthread_t tid;

int ret = pthread_create(&tid,NULL,&thread_func,NULL);
if(ret)
{
printf("Thread create failed.\n");
exit(1);
}
pthread_detach(tid);

int retk = pthread_join(tid,(void**)&retval);
if(retk)
printf("Can't get thread return state.errno = %d\n",ret);

// printf("a = %d,b = %d \n",retval->a,retval->b);


pthread_exit(NULL);
}

******************************************************************************************************

 

 

加入pthread_detach()之后,pthread_join()失败。

 

三  杀死线程  pthread_cancel(pthrad_t thread);

  线程的取消并不是实时的,而是要等到一个结束点才可以。一般是一个新系统调用。

  如果线程中没有系统调用,可以调用pthread_testcancel(); 此函数没有实际意义,仅仅是给线程的取消提供一个点。

  被取消的线程,退出值定义在linux的pthread库中。常数PTHREAD_CANCELED的值为-1.可在头文件pthread.h中找到它的定义:

   #define PTHREAD_CANCELED ((void*)-1).因此当我们对一个被取消的线程使用pthread_join()回收,返回值为-1.

 

------------恢复内容开始------------

管道--pipe

管道的概念:

      管道是一种最基本的IPC机制,作用于有血缘关系的进程之间来完成数据传递。调用pipe系统调用即可创建管道。

      管道实际上是内核使用环形队列机制,借助内核缓冲区(4K)实现。

      管道的本质是一个伪文件; 有两个文件描述符,一个读,一个写端,数据从写端流入,读端流出。

缺点:

    1、管道采用半双工通信机制。

    2、只能在有公共祖先的进程间使用管道。

    3、数据一旦读走,就不存在,不可反复读取。

    4、数据自己读不能自己写。

 

int pipe(int fd[2]);  成功返回 0 ;失败返回 -1,设置errno 

fd[0]是读端;fd[1]是写端。创建成功后,创建该管道的进程同时拥有管道的读,写端。

在写进程需要手动关闭fd[0],在读进程需要手动关闭fd[1];

***********************************************************************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

//执行命令:./应用名 源文件名 目标文件名 进程数量

int main(int argc,char *argv[])
{

pid_t pid;
int ret;
int fd[2];

char rbuf[32];


ret = pipe(fd);
if(ret)
{
printf("pipe() error.\n");
exit(1);
}


pid = fork();
if(pid < 0)
{
printf("fork error\n");
exit(1);
}
else if(0 == pid)
{
char wbuf[] = "acdbgvgyva";
//关闭读端 fd[0]
close(fd[0]);
while(1)
{
write(fd[1],wbuf,strlen(wbuf));
sleep(1);
}

}
else
{
sleep(1); //保证先写,没有也可以
char rbuf[32] = {0};
//关闭写端 fd[1]
close(fd[1]);
while(1)
{
read(fd[0],rbuf,sizeof(rbuf));
printf("Read from pipe :%s\n",rbuf);
sleep(1);
}
}


return 0;
}

***********************************************************************************************************************************

执行结果:

 

 

------------恢复内容结束------------

posted @ 2020-08-14 21:01  houlianpi  阅读(180)  评论(0)    收藏  举报