How to print using g++ with printf correctly? - g++

I am compiling this code with g++:
#include <pthread.h>
#include <iostream>
#include <cstdlib>
#include <string>
#include <stdio.h>
using namespace std;
#define num_threads 3
#define car_limit 4
pthread_mutex_t mutex; // mutex lock
pthread_t cid; // thread id
pthread_attr_t attr; // thread attrubutes
void *OneCar(void *dir);
void ArriveBridge(int *direction);
void CrossBridge();
void ExitBridge(int *direction);
int main()
{
int dir[3] = {0,1,1};
pthread_mutex_init(&mutex, NULL);
pthread_attr_init(&attr);
//cout<< "Pthread Create" << endl;
printf("Pthread Create\n");
for(int i = 0; i < num_threads; i++)
{
pthread_create(&cid, &attr, OneCar, (void *)&dir[i]);
}
return 0;
}
void ArriveBridge(int *direction)
{
//cout<<"Arrive"<<*direction << endl;
int dr;
if(*direction == 0)
dr=0;
else
dr=1;
printf("Arrive%d", dr);
}
void CrossBridge(int *dir)
{
char d;
if(*dir == 0)
d = 'N';
else
d = 'S';
//cout<<"Crossing Bridge going:"<<d<<endl;
printf("Crossing Bridge going %c", d);
}
void ExitBridge(int *direction)
{
//cout<<"Exit" <<*direction<<endl;
int dr;
if(*direction == 0)
dr=0;
else
dr=1;
printf("Exit%d\n", dr);
}
void *OneCar(void *dir)
{
int *cardir;
cardir = (int *) dir;
//cout<<*cardir;
ArriveBridge(cardir);
CrossBridge(cardir);
ExitBridge(cardir);
return 0;
}
and I am expecting this result printed to the screen:
> Pthread Create
> Arrive0Crossing Bridge going NExit0
> Arrive1Crossing Bridge going SExit1
> Arrive1Crossing Bridge going NExit1
But i get this instead:
Pthread Create
Arrive0Crossing Bridge going NExit0
Why doesnt it print the rest out?

You need to use "pthread_join" in main to wait for all threads to exit before your program terminates. You should also use an array to hold the id of each thread that you create:
pthread_t cid[num_threads]; // thread id`
You'll then want to call join on every thread you create:
for(int i = 0; i < num_threads; i++)
{
pthread_create(&cid[i], &attr, OneCar, (void *)&dir[i]);
}
for(int i = 0; i < num_threads; ++i)
{
pthread_join(cid[i], NULL);
};
Running the modified code now gives:
Pthread Create
Arrive0Crossing Bridge going NExit0
Arrive1Crossing Bridge going SExit1
Arrive1Crossing Bridge going SExit1

Have you tried joining your threads at the end of main? It could be that the program is terminating before the other threads are completely finished.

You missed the newlines ("\n"):
printf("Arrive%d\n", dr);
printf("Crossing Bridge going %c\n", d);
Because of that, the streams are probably not flushed. Additionally, if you don't wait for your threads (pthread_join) your program will exit before the threads could do their work.

Related

How can I stop the program inside the a parent or a child process?

I have this piece of code that I developed just to address a problem that I have in another large program that I am developing.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <string>
#include <iostream>
using namespace std;
void processLine (char []);
void readLine(char []);
const int LIMIT = 512;
int main(int argc, char *argv[])
{
char oneLine[LINE_MAX];
readLine(oneLine);
return 0;
}
void readLine(char line[])
{
processLine(line);
//Otherstuff
------------
}
void processLine(char line[])
{
pid_t process;
int child_status;
string input;
cout << "Input: ";
cin >> input;
process = fork();
if(process == 0)
{ // do nothing
}
else
{
//parent
if(input == "quit")
{
printf("Quit command found ! \nExiting ");
for(int i = 0;i < 3;i++)
{
printf(".");
fflush(stdout);
sleep(1);
}
printf("\n");
exit(0);
}
else
{
wait(&child_status);
}
}
}
My goal is simple, When the user enter quit.
I will just display
Quit command found
Exiting ...
And there is a delay of one second between each of these three dots.
However the output that I get is
Quit command found
Exiting . other stuff ..
However, what seems to happen is that the parent process returns and then executes other stuff from the calling function before it continues to print the other two dots. How would I avoid the parent process from doing that ?
Use waitpid() like this:
pid_t childPid;
childPid = fork();
...
int returnStatus;
waitpid(childPid, &returnStatus, 0); // Parent process waits here for child to terminate.
Use it here
if(childPid == 0) // fork succeeded
{
// Do something
exit(0);
}
else // Main (parent) process after fork succeeds
{
int returnStatus;
waitpid(childPid, &returnStatus, 0);
}

Is it meaningful for a child to create its own child (by calling fork)?

Is it meaningful for a child to create its own child (by calling fork)?
In the following code I am unable to understand the effect of the child calling the fork:
#include <stdio.h>
#include <sys/types.h>
#define MAX_COUNT 200
void ChildProcess(void); /* child process prototype */
void ParentProcess(void); /* parent process prototype */
void main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
}
void ChildProcess(void)
{
int i;
fork(); // child creates its own child process
for (i = 1; i <= MAX_COUNT; i++)
printf(" This line is from child, value = %d\n", i);
printf(" *** Child process is done ***\n");
}
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
}
Any process can call fork(), this way a tree of processes may be formed.
That is what happens in your example, the printouts of ChildProcess will appear twice.

Need help in getting the process name based on the pid in aix

I need to write a C program in AIX environment which will give me the process name.
I can get the pid but not the process name based on the pid. Any specific system calls available in aix environment??
Thanks
getprocs is likely what you want. I created this under AIX 5.x.
I have a little routine that cycles thru all processes and dumps their information.
while ((numproc = getprocs(pinfo, sizeof(struct procsinfo),
NULL,
0,
&index,
MAXPROCS)) > 0 ) {
for (i = 0;i < numproc; i++) {
/* skip zombie processes */
if (pinfo[i].pi_state==SZOMB)
continue;
printf("%-6d %-4d %-10d %-16s\n", pinfo[i].pi_pid, pinfo[i].pi_uid, pinfo[i].pi_start, pinfo[i].pi_comm);
}
}
....
I realize this is an old question.
But, to convert the #CoreyStup answer into a function that more closely addresses the OP, I offer this: (tested on AIX 6.1, using: g++ -o pn pn.cc)
--- pn.cc ---
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <procinfo.h>
#include <sys/types.h>
using namespace std;
string getProcName(int pid)
{
struct procsinfo pinfo[16];
int numproc;
int index = 0;
while((numproc = getprocs(pinfo, sizeof(struct procsinfo), NULL, 0, &index, 16)) > 0)
{
for(int i=0; i<numproc; ++i)
{
// skip zombies
if (pinfo[i].pi_state == SZOMB)
continue;
if (pid == pinfo[i].pi_pid)
{
return pinfo[i].pi_comm;
}
}
}
return "";
}
int main(int argc, char** argv)
{
for(int i=1; i<argc; ++i)
{
int pid = atoi(argv[i]);
string name = getProcName(pid);
cout << "pid: " << pid << " == '" << name << "'" << endl;
}
return 0;
}

USB applications using libusb library

I want to use libusb library for writing some test applications for USB.
Can any one please suggest how to set control transfers using usb_control_msg call?
I am getting bad descriptor error while running the following code.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "usb.h"
static int vendor_id;
static int product_id;
typedef struct{
int requesttype;
int request;
int value;
int index;
char *bytes;
int size;
int timeout;
}ctrlmsg_param;
void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
printf("=====End point Information====\n");
printf("bEndpointAddress: %x\n", endpoint->bEndpointAddress);
printf("bmAttributes: %x\n", endpoint->bmAttributes);
printf("wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf("bInterval: %d\n", endpoint->bInterval);
printf("bRefresh: %d\n", endpoint->bRefresh);
printf("bSynchAddress: %d\n", endpoint->bSynchAddress);
}
void print_altsetting(struct usb_interface_descriptor *interface)
{
int i;
printf("\n=====Alternate Setting Information====\n");
printf("bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf("bAlternateSetting: %d\n", interface->bAlternateSetting);
printf("bNumEndpoints: %d\n", interface->bNumEndpoints);
printf("bInterfaceClass: %d\n", interface->bInterfaceClass);
printf("bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf("bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf("iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
void print_configuration(struct usb_config_descriptor *config)
{
int i;
printf("=====Configuration Information====\n");
printf("wTotalLength: %d\n", config->wTotalLength);
printf("bNumInterfaces: %d\n", config->bNumInterfaces);
printf("bConfigurationValue: %d\n", config->bConfigurationValue);
printf("iConfiguration: %d\n", config->iConfiguration);
printf("bmAttributes: %x\n", config->bmAttributes);
printf("MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
int print_device(struct usb_device *dev)
{
usb_dev_handle *udev;
char str[100];
int ret, i;
udev = usb_open(dev);
if (udev) {
if (dev->descriptor.iManufacturer) {
ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, str, sizeof(str));
if (ret > 0)
{
printf("Manufacturer is %s\n",str);
}
}
if (dev->descriptor.iProduct) {
ret = usb_get_string_simple(udev, dev->descriptor.iProduct, str, sizeof(str));
if (ret > 0)
{
printf("Product is %s\n",str);
}
}
}
if (udev)
usb_close(udev);
printf("Possible configurations are %x\n",dev->descriptor.bNumConfigurations);
sleep(2);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
print_configuration(&dev->config[i]);
return 0;
}
int htod( const char* str )
{
int decimal;
sscanf( str, "%x", &decimal);
return decimal;
}
void set_data(struct usb_device *dev)
{
ctrlmsg_param param;
param.requesttype= 0;
param.request=0;
param.value=0;
param.index=0;
param.bytes=10;
param.size=0;
param.timeout=5000;
usb_control_msg(dev, param.requesttype, param.request, param.value, param.index, param.bytes, param.size, param.timeout);
printf("error is %s\n",strerror(errno));
return;
}
int main(int argc, char *argv[])
{
struct usb_bus *bus;
struct usb_device *dev;
if(argc != 3)
{
printf("Error in number of arguments\n");
printf("Usage:./usb_info <vendor id> <product id>\n");
exit(0);
}
vendor_id=htod(argv[1]);
product_id=htod(argv[2]);
printf("initializing USB library\n");
usb_init();
printf("Finding Buses and Devices\n");
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if ((dev->descriptor.idProduct == product_id) && (dev->descriptor.idVendor == vendor_id)){
printf("Found device with produxt id %x and vendor id %x\n",product_id,vendor_id);
print_device(dev);
set_data(dev);
print_device(dev);
}
}
}
return 0;
}
Regards,
Sandeep
I think that you mean usb_control_msg() is returns an error code for "bad descriptor". Please clarify if this is incorrect.
USB control transfers have some very specific formatting rules, and if the packet you are forming is sent to any compliant device, it will return a request error / stall on the bus.
You are sending the control transfer:
bmRequestType = 0x00
bRequest = 0x00
wValue = 0x0000
wIndex = 0x0000
wSize = 0x0000
this should be interpreted by the USB device as a GET_STATUS request, so wLength is required to be 2, and bmRequestType needs to have the top bit set, indicating this is an IN direction request (from the host's point of view). This is all from Chapter 9 of the USB specification 1.1/2.0/3.1 available at www.usb.org.
The parameter char *bytes (your param.bytes) also needs to be an address/pointer in the call you are making.
A good standard control transfer to test with would be:
bmRequestType = 0x80
bRequest = 0x06
wValue = 0x0001
wIndex = 0x0000
wSize = 0x0008
This request will return the first 8 bytes of the Device Descriptor, it is valid for every USB device, in all states.
The other transfer types (bulk, interrupt) don't have these strict formatting rules, and can be an easier place to start. I'd imagine you have already moved past this issue, since the question has been posted for quite a while, but maybe this response will still help someone else.

True non-blocking two-way communication between parent and external child process

I have read around 50 posts and tutorials on this topic, I have copied, written and tested around 20 alternatives and done every possible research I can think of. Still, I have not seen a working solution for the following problem:
Parent process A wants to pass data to an external process B, let process B modify the data and pass it back to parent process A, then continue with parent process A. Process B is part of an external program suite that I have no influence over, and that is normally run like this on the UNIX command line:
< input_data program_B1 | program_B2 | program_B3 > output_data
...where
input_data, output_data: Some data that is processed in programs B1-B3
program_B1,B2,B3: Programs that read data from stdin (fread) and output to stdout (fwrite) and apply some processing to the data.
So, in sequence:
(1) Parent process A passes data to child process B
(2) Child process B reads data and modifies it
(3) Child process B passes data back to parent process A
(4) Parent process A reads data and continues (for example passing it further on to a process B2..).
(5) Parent process A passes another data set to child process B etc.
The problem is, whatever I do, the program almost always ends up hanging on a read/fread (or write/fwrite?) to or from a pipe.
One important thing to note is that the parent process cannot simply close the pipes after passing data on to the child process, because it works in a loop and wants to pass another set of data to the child process once it has finished processing the first set.
Here is a working set of parent/child programs (compile with g++ pipe_parent.cc -o pipe_parent, g++ pipe_child.cc -o pipe_child) illustrating the problem with unnamed pipes. I have also tried named pipes, but not as extensively. Each execution can have a slightly different outcome. If the sleep statement is omitted in the parent, or the fflush() statement is omitted in the child, the pipes will almost surely block. If the amount of data to be passed on is increased, it will always block independent of the sleep or fflush.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
}
using namespace std;
/*
* Parent-child inter-communication
* Child is external process
*/
int main() {
int fd[2];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
}
int fd_parentWrite = fd[1];
int fd_childRead = fd[0];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
exit(-1);
}
int fd_childWrite = fd[1];
int fd_parentRead = fd[0];
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
exit(-1);
}
if( pid == 0 ) { // Child process
dup2( fd_childRead, fileno(stdin) ); // Redirect standard input(0) to child 'read pipe'
dup2( fd_childWrite, fileno(stdout) ); // Redirect standard output(1) to child 'write pipe'
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
// execl replaces child process with an external one
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
exit(-1);
// Child process is done. Will not continue from here on
}
else { // Parent process
// Nothing to set up
}
// ...more code...
if( pid > 0 ) { // Parent process (redundant if statement)
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
buffer[i] = (float)i;
}
for( int iter = 0; iter < 5; iter++ ) {
fprintf(stderr,"--------- Iteration #%d -----------\n", iter);
int sizeWrite = (int)write( fd_parentWrite, buffer, totalSize );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
fprintf(stderr,"Parent #%d: Wrote %d elements. Total size: %d\n", iter, sizeWrite, totalSize);
sleep(1); // <--- CHANGE!
int sizeRead = (int)read( fd_parentRead, buffer, totalSize );
if( sizeRead <= 0 ) {
fprintf(stderr,"Parent process read error\n");
}
while( sizeRead < totalSize ) {
fprintf(stderr,"Parent #%d: Read %d elements, continue reading...\n", iter, sizeRead);
int sizeNew = (int)read( fd_parentRead, &buffer[sizeRead], totalSize-sizeRead );
fprintf(stderr," ...newly read %d elements\n", sizeNew);
if( sizeNew < 0 ) {
exit(-1);
}
sizeRead += sizeNew;
}
fprintf(stderr,"Parent #%d: Read %d elements. Total size: %d\n", iter, sizeRead, totalSize);
fprintf(stderr,"Examples : %f %f %f\n", buffer[0], buffer[10], buffer[100]);
}
delete [] buffer;
}
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
fprintf(stderr,"Child #%d: Read %d elements, buffer100: %f\n", counter, sizeRead, buffer[100]);
if( sizeRead > 0 ) {
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fflush(stdout); // <--- CHANGE!
fprintf(stderr,"Child #%d: Wrote %d elements\n", counter, sizeWrite);
counter += 1;
}
} while( sizeRead > 0 );
return 0;
}
Is there any way to check when the pipe has enough data to be read? Or is there an alternative way to resolve the above problem, with or without pipes?
Please help!
Possibly the best solution when reading is to check with select whether you can read from the pipe. You can even pass a timeout. The alternative might be setting the O_NONBLOCK flag on file descriptor 0 (stdin) with fcntl, though I think the select way is better.
As with ensuring non-blocking write: that's a bit harder as you don't know how much you can write before the pipe blocks. One way (that I feel is very ugly) would be to only write 1 byte chunks and again check with select whether you can write. But that would be a performance killer, so use only if performance in communication is not an issue.
The first answer (using select to find out whether a pipe is ready to be read from) was good but didn't really solve my issue, see also my previous comments. Sooner or later I always ended up with a "race condition" where the program kept hanging either on a read or write.
The solution (maybe not be the only one?) is to run the child-to-parent data transfer in a different thread. I also went back and implemented the pipes as named pipes. It would probably also work with unnamed pipes but I didn't check that.
The final code is below. Note that no explicit flushing is required; the parent-to-child and child-to-parent data transfers are now decoupled. Any comments how this can be improved welcome! One residual problem I can see is that the pipes may fill up depending on how long time the child needs to process the data. I'm not sure how likely this is to happen. And by the way this worked fine with my external programs, not only with the provided child program.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
}
using namespace std;
static int const READING = -1;
static int const BUFFER_READY = 1;
static int const FINISHED = 0;
/*
* Parent-child inter-communication
* Child is external process
*/
struct threadStruct {
FILE* file_c2p;
int sizeBuffer;
float* buffer;
int io_flag;
};
// Custom sleep function
void mini_sleep( int millisec ) {
struct timespec req={0},rem={0};
time_t sec = (int)(millisec/1000);
millisec = (int)(millisec-(sec*1000));
req.tv_sec = sec;
req.tv_nsec = millisec*1000000L;
nanosleep(&req,&rem);
}
// Function to be executed within separate thread: Reads in data from file pointer
// Hand-shaking with main thread is done via the flag 'io_flag'
void *threadFunction( void *arg ) {
threadStruct* ptr = (threadStruct*)arg;
ptr->io_flag = READING;
while( ptr->io_flag != FINISHED ) {
if( ptr->io_flag == READING ) {
int sizeRead = fread( ptr->buffer, 1, ptr->sizeBuffer, ptr->file_c2p );
if( sizeRead <= 0 ) {
ptr->io_flag = FINISHED;
return NULL;
}
ptr->io_flag = BUFFER_READY;
}
else {
mini_sleep(10);
}
}
return NULL;
}
//--------------------------------------------------
int main() {
std::string filename_p2c("/tmp/fifo11_p2c");
std::string filename_c2p("/tmp/fifo11_c2p");
fprintf(stderr,"..started\n");
int status = mknod(filename_p2c.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
status = mknod(filename_c2p.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
FILE* file_dump = fopen("parent_dump","w");
int fd_p2c;
int fd_c2p;
FILE* file_c2p = NULL;
//--------------------------------------------------
// Set up parent/child processes
//
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
}
if( pid == 0 ) { // Child process
fd_p2c = open( filename_p2c.c_str(), O_RDONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
fd_c2p = open( filename_c2p.c_str(), O_WRONLY );
if( fd_c2p < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
dup2(fd_p2c,fileno(stdin)); // Redirect standard input(0) to child 'read pipe'
dup2(fd_c2p,fileno(stdout)); // Redirect standard output(1) to child 'write pipe'
close(fd_p2c);
close(fd_c2p);
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
kill( getppid(), 9 ); // Kill parent process
exit(-1);
}
else { // Parent process
fd_p2c = open( filename_p2c.c_str(), O_WRONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
file_c2p = fopen( filename_c2p.c_str(), "r");
fd_c2p = fileno( file_c2p );
if( fd_c2p < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
}
int numElements = 10000;
int sizeBuffer = numElements * sizeof(float);
float* bufferIn = new float[numElements];
float* bufferOut = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
bufferIn[i] = 0.0;
}
int numIterations = 5;
int numBytesAll = numElements * sizeof(float) * numIterations;
pthread_t thread;
threadStruct* threadParam = new threadStruct();
threadParam->file_c2p = file_c2p;
threadParam->sizeBuffer = sizeBuffer;
threadParam->buffer = bufferIn;
threadParam->io_flag = READING;
int thread_stat = pthread_create( &thread, NULL, threadFunction, threadParam );
if( thread_stat < 0 ) {
fprintf(stderr,"Error when creating thread\n");
exit(-1);
}
int readCounter = 0;
int numBytesWrite = 0;
int numBytesRead = 0;
for( int iter = 0; iter < numIterations; iter++ ) {
for( int i = 0; i < numElements; i++ ) {
bufferOut[i] = (float)i + iter*numElements*10;
}
int sizeWrite = (int)write( fd_p2c, bufferOut, sizeBuffer );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
numBytesWrite += sizeWrite;
fprintf(file_dump,"Parent #%d: Wrote %d/%d bytes.\n", iter, numBytesWrite, numBytesAll);
if( iter == numIterations-1 ) close(fd_p2c); // Closing output pipe makes sure child receives EOF
if( threadParam->io_flag != READING ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
}
//********************************************************************************
//
fprintf(file_dump,"------------------------------\n");
while( threadParam->io_flag != FINISHED ) {
if( threadParam->io_flag == BUFFER_READY ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
else {
mini_sleep(10);
}
}
// wait for thread to finish before continuing
pthread_join( thread, NULL );
fclose(file_dump);
fclose(file_c2p);
waitpid(pid, &status, 0); // clean up any children
fprintf(stderr,"..finished\n");
delete [] bufferIn;
delete [] bufferOut;
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
FILE* file_dump = fopen("child_dump","w");
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
if( sizeRead > 0 ) {
fprintf(file_dump,"Child #%d: Read %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fprintf(file_dump,"Child #%d: Wrote %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
counter += 1;
}
} while( sizeRead > 0 );
fprintf(file_dump,"Child is finished\n");
fclose(file_dump);
fclose(stdout);
return 0;
}