แสดงตัวอย่างการใช้ popen() เพื่อรับข้อมูลที่อ่านได้จากคำสั่ง ls แล้วส่งต่อไปเป็นอินพุทให้กับอีกคำสั่ง (sort) เพื่อทำการจัดเรียงข้อมูลต่อไป
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *pipein_fp, *pipeout_fp;
char readbuf[80];
/* Create one way pipe line with call to popen() */
if ((pipein_fp = popen("ls /", "r")) == NULL) {
perror("popen");
exit(1);
}
/* Create one way pipe line with call to popen() */
if ((pipeout_fp = popen("sort", "w")) == NULL) {
perror("popen");
exit(1);
}
/* Processing loop */
while (fgets(readbuf, 80, pipein_fp))
fputs(readbuf, pipeout_fp);
/* Close the pipes */
pclose(pipein_fp);
pclose(pipeout_fp);
return (0);
}
$ ls /
NAS courseweb_backup etc initrd.img.old lib64 mnt root selinux tftpboot var bin dev home lib lost+found opt run srv tmp vmlinuz boot ee_backup initrd.img lib32 media proc sbin sys usr vmlinuz.old
$ gcc -o pipe3 pipe3.c -Wall
$ ./pipe3
NAS
bin
boot
courseweb_backup
dev
ee_backup
etc
home
initrd.img
initrd.img.old
lib
lib32
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
selinux
srv
sys
tftpboot
tmp
usr
var
vmlinuz
vmlinuz.old
ตัวอย่างที่ 4
แสดงตัวอย่างการรับอาร์กิวเมนต์จากผู้ใช้ผ่านการเรียกโปรแกรมจาก command line โดยอาร์กิวเมนต์ตัวแรกจะเป็นคำสั่งที่ต้องการให้รับข้อมูล (write) และอาร์กิวเมนต์ที่สองจะเป็นไฟล์ข้อมูลที่ต้องการจะให้เปิดอ่าน (rt)
/*****************************************************************************
Excerpt from "Linux Programmer's Guide - Chapter 6"
(C)opyright 1994-1995, Scott Burkett
*****************************************************************************
Filename: popen.c
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
FILE *pipe_fp, *infile;
char readbuf[80];
if (argc != 3) {
fprintf(stderr, "USAGE: popen3 [command] [filename]\n");
exit(1);
}
/* Open up input file */
if ((infile = fopen(argv[2], "rt")) == NULL) {
perror("fopen");
exit(1);
}
/* Create one way pipe line with call to popen() */
if ((pipe_fp = popen(argv[1], "w")) == NULL) {
perror("popen");
exit(1);
}
/* Processing loop */
do {
fgets(readbuf, 80, infile);
if (feof(infile))
break;
fputs(readbuf, pipe_fp);
} while (!feof(infile));
fclose(infile);
pclose(pipe_fp);
return (0);
}
แสดงตัวอย่างการประยุกต์การส่งข้อความ (message) ระหว่างโปรเซสต่างๆ โดยโปรเซสที่ i ต้องการส่งไปยังโปรเซสที่ j โดยถ้าโปรเซสใดรับข้อความเพียงสองครั้งแล้วก็จะสิ้นสุดการทำงาน
/*
* pipe4.c
*
* A set of processes randomly messaging each the other, with pipes.
*
*
* Created by Mij <mij@bitchx.it> on 05/01/05.
* Original source file available on http://mij.oltrelinux.com/devel/unixprg/
*
*/
#include <stdio.h>
/* for read() and write() */
#include <sys/types.h>
#include <sys/uio.h>
/* for strlen and others */
#include <string.h>
/* for pipe() */
#include <unistd.h>
/* for [s]random() */
#include <stdlib.h>
/* for time() [seeding srandom()] */
#include <time.h>
/* for signals */
#include <signal.h>
#define PROCS_NUM 15 /* 1 < number of processes involved <= 255 */
#define MAX_PAYLOAD_LENGTH 50 /* message length */
#define DEAD_PROC -1 /* a value to mark a dead process' file descriptors with */
/* *** DATA TYPES *** */
/* a process address */
typedef char proc_addr;
/* a message */
struct message_s {
proc_addr src_id;
short int length;
char *payload;
};
/* *** FUNCTION PROTOTYPES *** */
/* send message to process with id dest */
int send_proc_message(proc_addr dest, char *message);
/* receive a message in the process' queue of received ones */
int receive_proc_message(struct message_s *msg);
/* mark process file descriptors closed */
void mark_proc_closed(proc_addr process);
/* *** GLOBAL VARS *** */
/* they are OK to be global here. */
proc_addr my_address; /* stores the id of the process */
int proc_pipes[PROCS_NUM][2]; /* stores the pipes of every process involved */
int main(int argc, char *argv[]) {
pid_t child_pid;
pid_t my_children[PROCS_NUM]; /* PIDs of the children */
int i, ret;
char msg_text[MAX_PAYLOAD_LENGTH]; /* payload of the message to send */
proc_addr msg_recipient;
struct message_s msg;
/* create a pipe for me (the parent) */
pipe(proc_pipes[0]);
/* initializing proc_pipes struct */
for (i = 1; i < PROCS_NUM; i++) {
/* creating one pipe for every (future) process */
ret = pipe(proc_pipes[i]);
if (ret) {
perror("Error creating pipe");
abort();
}
}
/* fork [1..NUM_PROCS] children. 0 is me. */
for (i = 1; i < PROCS_NUM; i++) {
/* setting the child address */
my_address = my_address + 1;
child_pid = fork();
if (!child_pid) {
/* child */
sleep(1);
/* closing other process' pipes read ends */
for (i = 0; i < PROCS_NUM; i++) {
if (i != my_address)
close(proc_pipes[i][0]);
}
/* init random num generator */
srandom(time(NULL));
/* my_address is now my address, and will hereby become a "constant" */
/* producing some message for the other processes */
while (random() % (2 * PROCS_NUM)) {
/* interleaving... */
sleep((unsigned int) (random() % 2));
/* choosing a random recipient (including me) */
msg_recipient = (proc_addr) (random() % PROCS_NUM);
/* preparing and sending the message */
sprintf(msg_text, "hello from process %u.", (int) my_address);
ret = send_proc_message(msg_recipient, msg_text);
if (ret > 0) {
/* message has been correctly sent */
printf(" --> %d: sent message to %u\n", my_address,
msg_recipient);
} else {
/* the child we tried to message does no longer exist */
mark_proc_closed(msg_recipient);
printf(" --> %d: recipient %u is no longer available\n",
my_address, msg_recipient);
}
}
/* now, reading the first 2 messages we've been sent */
for (i = 0; i < 2; i++) {
ret = receive_proc_message(&msg);
if (ret < 0)
break;
printf(
"<-- Process %d, received message from %u: \"%s\".\n",
my_address, msg.src_id, msg.payload);
};
/* i'm exiting. making my pipe widowed */
close(proc_pipes[my_address][0]);
printf("# %d: i am exiting.\n", my_address);
exit(0);
}
/* saving the child pid (for future killing) */
my_children[my_address] = child_pid;
/* parent. I don't need the read descriptor of the pipe */
close(proc_pipes[my_address][0]);
/* this is for making srandom() consistent */
sleep(1);
}
/* expecting the user request to terminate... */
printf("Please press ENTER when you like me to flush the children...\n");
getchar();
printf("Ok, terminating dandling processes...\n");
/* stopping freezed children */
for (i = 1; i < PROCS_NUM; i++) {
kill(my_children[i], SIGTERM);
}
printf("Done. Exiting.\n");
return 0;
}
int send_proc_message(proc_addr dest, char *message) {
int ret;
char *msg = (char*) malloc(sizeof(message) + 2);
/* the write should be atomic. Doing our best */
msg[0] = (char) dest;
memcpy((void*) &(msg[1]), (void*) message, strlen(message) + 1);
/* send message, including the "header" the trailing '\0' */
ret = write(proc_pipes[dest][1], msg, strlen(msg) + 2);
free(msg);
return ret;
}
int receive_proc_message(struct message_s *msg) {
char c = 'x';
char temp_string[MAX_PAYLOAD_LENGTH];
int ret, i = 0;
/* first, getting the message sender */
ret = read(proc_pipes[my_address][0], &c, 1);
if (ret == 0) {
return 0;
}
msg->src_id = (proc_addr) c;
do {
ret = read(proc_pipes[my_address][0], &c, 1);
temp_string[i++] = c;
} while ((ret > 0) && (c != '\0') && (i < MAX_PAYLOAD_LENGTH));
if (c == '\0') {
/* msg correctly received. Preparing message packet */
msg->payload = (char*) malloc(strlen(temp_string) + 1);
strncpy(msg->payload, temp_string, strlen(temp_string) + 1);
return 0;
}
return -1;
}
void mark_proc_closed(proc_addr process) {
proc_pipes[process][0] = DEAD_PROC;
proc_pipes[process][1] = DEAD_PROC;
}
$ gcc --ansi --pedantic -o pipe4 pipe4.c
$ ./pipe4
--> 1: sent message to 3
--> 1: sent message to 8
--> 2: sent message to 0
--> 1: sent message to 5
--> 2: sent message to 4
--> 1: sent message to 10
--> 2: sent message to 9
--> 2: sent message to 0
--> 3: sent message to 11
--> 2: sent message to 6
--> 1: sent message to 2
--> 2: sent message to 12
--> 3: sent message to 14
<-- Process 4, received message from 4: "hello from process 2.".
--> 3: sent message to 13
--> 1: sent message to 3
--> 1: sent message to 9
--> 1: sent message to 12
--> 1: sent message to 3
--> 2: sent message to 6
--> 3: sent message to 7
<-- Process 5, received message from 5: "hello from process 1.".
--> 2: sent message to 12
--> 2: sent message to 5
--> 1: sent message to 7
--> 1: sent message to 4
<-- Process 4, received message from 0: "hello from process 1.".
# 4: i am exiting.
--> 1: sent message to 12
--> 1: sent message to 2
<-- Process 5, received message from 0: "hello from process 2.".
# 5: i am exiting.
--> 2: sent message to 14
--> 2: sent message to 1
--> 2: sent message to 10
--> 1: sent message to 8
--> 1: sent message to 0
--> 1: sent message to 0
--> 6: sent message to 13
--> 6: sent message to 8
--> 6: sent message to 14
--> 8: sent message to 14
--> 6: sent message to 14
--> 8: sent message to 8
--> 8: sent message to 11
--> 9: sent message to 14
--> 10: sent message to 0
^C