I am working on an assignment and I need to create pipes so that other programs handle different functions. I am able to pipe through the command line no problem, thats easy. However using dup2 and execl have been tricky for me. At one point I was able to get output from one part of my program but it wasn't reading anything in from another part.
here is what i have:
pipeline.cpp
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <cstdlib>
#include <iostream>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<iomanip>
#include <sys/wait.h>
using namespace std;
int main(int argc, char *argv[])
{
int number = atoi(argv[1]);
int x2ypipe[2];
pipe(x2ypipe);
if(x2ypipe==0){
cout<<"ERROR:"<<errno<<endl;
}
pid_t xchild =fork();
if(xchild==0){
dup2(x2ypipe[1],STDOUT_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
execl("./part1.cpp","part1.cpp", (char *)NULL);
}
pid_t ychild =fork();
if(ychild==0){
dup2(x2ypipe[0],STDIN_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
execl("./part2.cpp", "part2.cpp", (char *)NULL);
}
close(x2ypipe[0]);
close(x2ypipe[1]);
wait(NULL);
wait(NULL);
part1.cpp
#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<iomanip>
using namespace std;
int main(int argc, char *argv[])
{
int number = atoi(argv[1]);
for (int k = 1; k <= 9; k++)
{
cout << k << " " << flush;
sleep(1);
}
return 0;
}
part2.cpp
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <iomanip>
using namespace std;
int main()
{
int number;
while (cin >> number)
{
cout << 2 * number - 1 << " " << flush;
}
return 0;
}
Ok so pipeline.cpp : forks twice and creates a pipe between the two children. Then each use excel to replace its process with the programs part1 and part2. So my understanding is that part1 program would run and anything it outputs will be picked up by the second child which runs part2 and from there part two would output normally since it's output descriptor wasn't changed. Am I missing or misusing something here?
I noticed a couple of things:
You're not passing the number to the part1 process when you exec it
You're not checking for failure from execl() or any of the other OS functions
I think once you do these two things, you'll find out what the real problem is. I won't just tell you what the answer is, because it's worthwhile learning how to diagnose such problems yourself. (I was able to run your code successfully with only minor modifications. The problem does not lie in how you're handling the pipes and file descriptors.)
I think you need to return 0; after your exec calls. But I am even more lost than you it seems.
Related
This question already has answers here:
Does endless While loop take up CPU resources?
(3 answers)
why does an infinite loop of the unintended kind increase the CPU use?
(4 answers)
Does a while(true) Infinite Loop Peg the CPU? [closed]
(2 answers)
CPU usage increases for Empty Infinite While loop
(4 answers)
Closed last month.
I wrote some in c++ and try to execute it on raspberry pi . I noticed a CPU Load of 100 %
I then removed bit for bit from the code to see what causes the high load. Now my code looks like the code below (stripped of all functionality ) and it still has 99-100% load.
Can someone point me in the right direction ?
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <cmath>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
int main(int argc, char* argv[])
{
// Check command line arguments
if (argc < 3) {
cout << "Usage: Test can_name dbc_file" << endl;
return 1;
}
// Get can name and dbc file name from command line arguments
string canName = argv[1];
string dbcFileName = argv[2];
while (true) {
}
return 0;
}
I tried to strip my code of all funtionality to end up with a basic program that should have very little cpu load
Try adding a sleep within the loop like
while ( true ) {
usleep(100000); // sleeps for 100 ms
}
I know there is one in C, Sleep(ms), but is there one for C++? I am trying to return an error, then print to the console, then sleep enough for the user to read it before returning the errorcode. Code in C would be:
#include <stdio.h>
#include <windows.h>
int main (int argc, const char *argv[]) {
char *err = "Have an error!";
printf("Error: %s. Program terminating in 5 seconds...", err);
Sleep(5000);
return 1;
}
You could include <windows.h> and just call the WinApi function Sleep just as you would from C. This is mostly pure C++ :
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
using namespace std;
int main (int argc, const char *argv[]) {
string err = "Have an error!";
cout << "Error: " << err << ". Program terminating in 5 seconds..." << endl;
std::chrono::milliseconds timespan(5000);
std::this_thread::sleep_for(timespan);
return 1;
}
I'm having issue in the ifstream function, I have tried using the argv[1] as parameter but wont load the map, the map is located in the same folder of main code.
I'm stucked here and can not debug.
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
using namespace std;
int main (int argc, char *argv[]){
int h;
int w;
int var;
string inputLine;
ifstream f;
f.open("map.pgm",ios::in);
if (!f){
cout << "error" << endl;
exit(1);
}
I'm using Visual Studio 2017
Change this line:
if (!f){
by this:
if (!f.is_open()){
BTW you can check current directory path with GetModuleFileName
I want to clear L1, L2 and L3 cache 50 times by executing the following code. However it becomes very slow if I run it by typing sudo ./a.out. On the other hand, if I just write ./a.out it will finish executing almost instantly. I do not understand the reason for this since I am not getting any errors in the terminal.
#include <iostream>
#include <cstdlib>
#include <vector>
#include <fstream>
#include <unistd.h>
using namespace std;
void clear_cache(){
sync();
std::ofstream ofs("/proc/sys/vm/drop_caches");
ofs << "3" << std::endl;
sync();
}
int main() {
for(int i = 0; i < 50; i++)
clear_cache();
return 0;
};
You don't have enough permissions to write to this file as a regular user:
-rw-r--r-- 1 root root 0 Feb 11 15:56 /proc/sys/vm/drop_caches
Only version run as a privileged user works, hence it takes longer. The reason you're not getting any errors is that you're not checking any errors.
Here's the most simple check:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <fstream>
#include <unistd.h>
using namespace std;
void clear_cache(){
sync();
std::ofstream ofs("/proc/sys/vm/drop_caches");
if (!ofs)
{
std::cout << "could not open file" << std::endl;
exit(EXIT_FAILURE);
}
ofs << "3" << std::endl;
sync();
}
int main() {
for(int i = 0; i < 50; i++)
clear_cache();
return 0;
};
Output:
% ./a.out
could not open file
How do you have the user input the folder name and have it created in the desktop (for mac)?
This is what I have so far.. (and extra code underneath)
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main ()
{
char game_name [100];
cout << "Game Name: ";
cin >> game_name;
const char* homeDir = getenv ("Home");
char final [256];
sprintf (final, "%s/Desktop/%s",homeDir, game_name);
mkdir(final,0775);
other code....
....
...
..
return 0;
}
Environment variables are case sensitive, so you need to use getenv("HOME") instead of getenv("Home").
Use Boost Library (though there will be overhead of setting up boost on your system but its worth for doing many other stuffs in C++): boost::filesystem::create_directories()
#include <boost/filesystem.hpp>
// your code....
boost::filesystem::create_directories("/bla/a");