linux c++ 等待函数,Linux C++管道之pipe、dup、dup2、wait、waitpid、fork函数说明

pipe、dup、dup2、wait、waitpid、fork函数说明intpipe(intfd[2]);

功能:创建一个简单的管道,若成功则为数组fd分配两个文件描述符,其中fd[0] 用于读取管道,fd[1]用于写入管道。

返回:成功返回0,失败返回-1;

管道是Linux 支持的最初Unix IPC形式之一,具有以下特点:

管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道; 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程); 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系 统,并且只存在与内存中。 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

但值得我们注意的是:管道它有自身的特点。

(1)管道通信是单向的,并且遵守先进先出的原则,即先写入的数据先读出。

(2)管道是一个无结构,无固定大小的字节流。

(3)两个返回的文件描述符以一种特殊的方式连接起来.写到fd[1]的数据都可以从fd[0]中读回来.

向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。intdup(intfd)

复制一个存在的文件描述符,返回当前可用的最小文件描述符。。。比如当前文件描述符已经到了100,使用 dup(100) ,将返回101,101这个文件描述符拥有100的所有东西,复制了嘛。。。intdup2(intfd,intfd2)

是可以指定一个文件描述符(fd2)来使用,如果fd2已经打开,则会先将其关闭,如果 fd==fd2 ,直接返回 fd2 且不关闭。

实际上 fcntl 也能完成这2个函数的功能,只是对于 dup2 来说,fcntl 是调用2个函数,而 dup2 是一个原子操作。

dup函数的作用:复制一个现有的句柄,产生一个与“源句柄特性”完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备)

dup2函数的作用:复制一个现有的句柄到另一个句柄上,目标句柄的特性与“源句柄特性”完全一样(也即首先关闭目标句柄,与设备断连,接着从源句柄完全拷贝复制到目标句柄)

wait和waitpid函数

头文件

#include#include函数 pid_t wait (int*status);

进程一旦调用了 wait,就 立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息, 并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

wait(等待子进程中断或结束)

wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考waitpid()。

返回值

如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。

waitpid(等待子进程中断或结束)

相关函数 wait,fork

表头文件

#include#include定义函数 pid_t waitpid(pid_t pid,int*status,intoptions);

函数说明

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。

参数pid 为欲等待的子进程识别码,其他数值意义如下:

pid1等待进程组识别码为pid 绝对值的任何子进程。

pid=-1等待任何子进程,相当于wait()。

pid=0等待进程组识别码与目前进程相同的任何子进程。

pid>0等待任何子进程识别码为pid 的子进程。

目前在Linux中只支持WNOHANG和WUNTRACED两个选项,

WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。

WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。

如果我们不想使用它们,也可以把options设为0,如:

ret=waitpid(-1,NULL,0);

如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。

而WUNTRACED参数,用于跟踪调试,极少用到,就不说了。

查看linux源代码 unistd.h 我们会发现,其实 wait 就是经过包装的 waitpid:staticinline pid_t wait(int*wait_stat)

{returnwaitpid(-1,wait_stat,0);

}

可以用kill函数杀死子进程

kill(childPid,SIGKILL);

子进程的结束状态返回后存于status,下面有几个宏可判别结束情况:

WIFEXITED(status)如果子进程正常结束则为非0值。

WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。

WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真

WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。

WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。

WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。if(WIFEXITED(status))

{

printf("exited, status=%d/n", WEXITSTATUS(status));

}elseif(WIFSIGNALED(status)) {

printf("killed by signal %d/n", WTERMSIG(status));

}elseif(WIFSTOPPED(status)) {

printf("stopped by signal %d/n", WSTOPSIG(status));

}elseif(WIFCONTINUED(status)) {

printf("continued/n");

}

返回值

如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。

fork函数

Create anewprocess

程序段里用了fork();之后程序出了分岔,派生出了两个进程。具体哪个先运行就看该操作的系统的调度算法了。

函数返回2次.

返回值得在子进程中pid的值为0,通过getpid可以获取子进程的进程id;

返回值:

A value of zero to the child process; and the process ID of the child process to the parent process.

Both processescontinueto execute from the fork() function. If an error occurs, fork() returns-1to the parent and sets errno.

#include#includeintmain()

{

pid_t pid;

puts("<1>");

pid=fork();if(pid<0) {

printf("error in fork! \r\n");

}elseif(pid==0) {

printf("i am the child process, my process id is %d \r\n",getpid());

}else{

printf("i am the parent process, my process id is %d \r\n",getpid());

}

puts("<2>");return0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Linux中的管道pipe)来获取命令行输出的内容。在C++中,可以通过fork()函数创建一个子进程,并在子进程中执行要获取输出的命令。然后,将子进程的标准输出重定向到管道的写端,父进程从管道的读端读取命令行输出。 下面是一个简单的示例代码: ```cpp #include <iostream> #include <unistd.h> #include <sys/wait.h> int main() { int pipefd[2]; pipe(pipefd); pid_t pid = fork(); if (pid == 0) { // 子进程中执行命令并将输出写入管道 close(pipefd[0]); // 关闭管道的读端 dup2(pipefd[1], STDOUT_FILENO); // 将标准输出重定向到管道的写端 // 执行命令 execlp("your_command", "your_command", nullptr); // 替换为你要执行的命令 // 执行失败则退出 std::cerr << "Failed to execute command" << std::endl; exit(1); } else { // 父进程从管道中读取命令行输出 close(pipefd[1]); // 关闭管道的写端 char buffer[4096]; ssize_t bytesRead; while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer))) > 0) { // 处理读取到的数据,例如打印输出 std::cout.write(buffer, bytesRead); } // 等待子进程结束 int status; waitpid(pid, &status, 0); } return 0; } ``` 在上面的代码中,需要将"your_command"替换为你要执行的命令。执行该程序时,它将创建一个子进程来执行命令,并将命令行输出通过管道传递给父进程,父进程则读取并处理输出。你可以根据需要对读取到的数据进行进一步处理或存储。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值