Looping a fork() - linux

This is a sample of my code for some piping I want to do. The problem is that pid2[0] does not supply me a child process. How do I fix it? pid2[1] and pid2[2] and so on do supply the parent with children.
int numCommands = numPipes + 1; /// not worrying about '>' and '<' right now
int *pipes = newint[numPipes*2]; /// two ends for each pipe
for(int i = 0; i < numPipes*2; i+=2) /// Offset by two since each pipe has two ends
pipe(pipes + i);
int *pid2 = new int [numCommands];
for(int i = 0; i < numCommands; i++)
{
pid2[i] = fork();
if(pid2[i] < 0)
{
std::cerr << "Failure to fork..." << std:endl;
return EXIT_FAILURE
}
if(pid2[i] == 0) /// Child process
{
if(i == 0) /// First Command
{
dup2(pipes[1], 1);
}
else if(i == numCommands -1) /// Last Command
{
dup2(pipes[2*(numCommands-1)-1], 0);
}
else /// Middle commands
{
dup2(pipes[2*(i-1)], 0);
dup2(pipes[(2*i)+1],1);
}
for(int j = 0; j < numPipes*2;j++)
close(pipes[j]);
execvp(pipeCommands[i][0], pipeCommands[i].data()); ///pipeCommands is a vector<vector<char*>>
perror("exec failed");
return EXIT_SUCCESS;
}
else /// The parent
{
for(int j = 0; j <numPipes*2;j++)
close(pipes[j]);
for(int k = 0; k < numCommands; k++)
waitpid(pid2[k],nullptr,0);
}
}

Your indexing into the pipes array is a little bit problematic. For sort file.txt | head | wc I'm assuming that numPipes is 2. Let's walk through your for loop for each value of i.
i==0
dup2(pipes[1], 1); // Send stdout to pipes[1]
i==1
dup2(pipes[2*(i-1)], 0); // dup2(pipes[0], 0), stdin from pipes[0]
dup2(pipes[(2*i)+1],1); // dup2(pipes[3], 1), stdout to pipes[3]
i == 2
dup2(pipes[2*(numCommands-1)-1], 0); //dup2(pipes[3], stdin from pipes[3]
In other words, any stdout from process 0 is going to a dead end. The second process will never read from its standard output. So the debug statement you put in there (cout == stdout, remember) will get lost as well.

Related

Implementing a custom command in a basic shell(in C)

I need to implement a custom command in a shell .The goal is to support a command program_name m that creates a child process to execute program_name, but aborts the process if it does not complete its operation in m seconds.
Actually I am checking the status of waitpid(child_pid,&exit_status,WUNTRACED) everytime ,but the code segment in the for loop is not working and is not aborting the process!!
Can anyone suggest me an appropriate routine from the library to deliver a SIGALRM signal after m seconds, and use a signal handler to perform appropriate actions?
Thanks in advance!!
int child_pid = fork();
if (child_pid < 0) {
perror("ERROR: could not fork process.\n");
}
if (child_pid == 0) {
char *args[4];
args[0] = path;
args[1] = "-c";
args[2] = command_line;
args[3] = (char *) 0;
//executing the command
int exec_return = execvp(path, args);
if (exec_return == -1) {
perror("error: command execution failed!\n");
} else {
exit(exec_return);
}
} else {
//assigning cur_fg_pid to the child
cur_fg_pid = child_pid + 1;
if (cur_fg_cmd == NULL) { cur_fg_cmd = (char *) malloc(sizeof(char)); }
strcpy(cur_fg_cmd, command_line);
int exit_status;
while (can_wait == 1 && waitpid(child_pid, &exit_status, 0) > 0) {}
cur_fg_pid = -1;
cur_fg_cmd = NULL;
if (can_wait == 1) latest_jobid = -1;
if(global_time_flag)
{
for (i = 0; i < stip_time; i++) {
if (waitpid(child_pid,&exit_status,WUNTRACED) > 0)
if (WIFSTOPPED(exit_status)) {
break;
} else {sleep(1);}
}
if(!WIFSTOPPED(exit_status ))
kill (child_pid, SIGUSR1);
}
}

Select in loop - work all the time - linux

I got next question about select:
How to make select in loop ?
I try to do like that:
struct timeval timeout;
int sel;
size_t rozmiar = sizeof(pid_t);
char buf[rozmiar];
int i;
FD_ZERO(&set);
for(i = 0; i< val; i++)
{ FD_SET(fd[i][0], &set); // val -> N pipe2
}
timeout.tv_sec = 2;
timeout.tv_usec = 0;
while(1)
{
sel = select(val+1,&set,NULL,NULL,&timeout);
if(sel < 0)
perror("select");
else if(sel == 0)
printf("No communicate \n");
else{
for(i = 0; i < val; i++)
{
if(FD_ISSET(fd[i][0],&set))
{
while(read(fd[i][0],&buf,rozmiar) > 0)
write(1,&buf,rozmiar);
} // check if exist and write to stdout
}
} // end SELECT
timeout.tv_sec = 2;
timeout.tv_usec = 0;
}
But there all the time show: ,, no communicate". Is it the correct way to create select which work all the time? I am not sure so I prefer to ask. I try to find information in books but with no lucky.
The set is changed by select, you need to refill it each time

I have some trouble with multi threading

I am struggling with this code. It's about counting some patterns from a text file. I tried to use thread(divide and conquer) processing, but it return a wrong value. I used mutex value to synchronize critical section.. The code is below. First main argument is number of threads, second is the name of a text file I want counting patterns from, and following patterns I want to look up on the text.
please save me..
Code is below
char *buffer;
int fsize, count;
char **searchword;
int *wordcount;
int *strlength;
typedef struct _params{
int num1;
int num2;
}params;
pthread_mutex_t mutex;
void *childfunc(void *arg)
{
int size, i, j, k, t, start, end, len, flag = -1;
int result;
params *a = (params *)arg;
start = a->num1;
end = a->num2;
while(1){
if(start == 0 || start == fsize)
break;
if(buffer[start]!= ' ' && buffer[start] != '\n' && buffer[start] != '\t')
start++;
else
break;
}
while(1){
if(end == fsize)
break;
if(buffer[end] != ' ' && buffer[end] != '\n' && buffer[end] != '\t')
end++;
else
break;
}
for(i = 0; i < count; i++){
len = strlength[i];
for(j = start; j<(end - len + 1); j++){
if(buffer[j] == searchword[i][0]){
flag = 0;
for(k = j +1; k<j + len; k++){
if(buffer[k] != searchword[i][k-j])
{
flag = 1;
break;
}
}
if(flag == 0){
pthread_mutex_lock(&mutex);
wordcount[i]++;
pthread_mutex_unlock(&mutex);// mutex unlocking
sleep(1);
flag = -1;
}
}
}
}
}
int main(int argc, char **argv){
FILE *fp;
char *inputFile;
pthread_t *tid;
int *status;
int inputNumber, i, j, diff, searchstart, searchend;
int result = 0;
count = argc -3;
inputNumber = atoi(argv[1]);
inputFile = argv[2];
searchword = (char **)malloc(sizeof(char *)*count);
tid = malloc(sizeof(pthread_t)*inputNumber);
strlength = (int *)malloc(4*count);
status = (int *)malloc(4*inputNumber);
wordcount = (int *)malloc(4*count);
for(i = 0; i < count; i++)
searchword[i] = (char*)malloc(sizeof(char)*(strlen(argv[i+3]) + 1));
for(i = 3; i < argc; i++)
strcpy(searchword[i-3], argv[i]);
fp = fopen(inputFile, "r");
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
rewind(fp);
buffer = (char *)malloc(1*fsize);
fread(buffer, fsize, 1, fp);
diff = fsize / inputNumber;
if(diff == 0)
diff = 1;
for(i = 0; i < count ; i++){
strlength[i] = strlen(searchword[i]);
wordcount[i] = 0;
}
for(i = 0; i < inputNumber; i++){
searchstart = 0 + i*diff;
searchend = searchstart + diff;
if(searchstart > fsize)
searchstart = fsize;
if(searchend > fsize)
searchend = fsize;
if( i == inputNumber -1)
searchend = fsize;
params a;
a.num1 = searchstart;
a.num2 = searchend;
pthread_mutex_init(&mutex, NULL);
result = pthread_create(&tid[i], NULL, childfunc, (void *)&a);
if(result < 0){
perror("pthread_create()");
}
}
//스레드 받는 부분
for(i = 0; i < inputNumber; i++){
result = pthread_join(tid[i], (void **)status);
if(result < 0)
perror("pthread_join()");
}
pthread_mutex_destroy(&mutex); // mutex 해제
for(i = 0; i < count; i++)
printf("%s : %d \n", searchword[i], wordcount[i]);
for(i = 0; i < count; i++) //동적메모리해제
free(searchword[i]);
free(searchword);
free(buffer);
free(tid);
free(strlength);
free(wordcount);
free(status);
fclose(fp);
return 0;
}
params a; // new a for each loop, previous a no longer exists
a.num1 = searchstart;
a.num2 = searchend;
pthread_mutex_init(&mutex, NULL);
result = pthread_create(&tid[i], NULL, childfunc, (void *)&a);
if(result < 0){
perror("pthread_create()");
}
} // a goes out of scope here
You pass each thread the address of a, but then a goes out of scope immediately after you create the thread. So the thread now has the address of some random leftover junk on the stack.
You need to have some conception of ownership of any object that's accessed by more than one thread like a is here. It can be owned by the thread that called pthread_create, owned by the newly-created thread, or jointly owned. But you have to be consistent. You have neither of these, why?
Is a owned only be the thread that called pthread_create? No, because the newly-created thread has a pointer to it and accesses it through that pointer. So the thread that called pthread_create cannot destroy it.
Is a owned only be the thread created by pthread_create? No, because it's on the stack of the thread that called pthread_create and will cease to exist when the next loop comes around.
Is a jointly owned? Well, no, because the thread that called pthread_create can destroy the object before the newly-created thread accesses it.
So no sane model of multi-thread use is followed by a. It's broken.
One common solution to this problem is to allocate a new structure (using malloc or new) for each thread, fill it in, and pass the thread the address of the structure. Let the thread free (or delete) the structure when it's done with it.

How to use PTHREAD_SETAFFINITY_NP correctly?

I am working on a program which have computationa based on a lot of data .So I created two threads.Their work is similar,but their data are different. I do this using the code below:
status1 = pthread_create(&pthread1,NULL,func_1,(void*)t1);
if(status1 != 0)
printf("pthread1 is not created sucessfully!\n");
status = pthread_create(&pthread2,NULL,func_2,(void*)t2);
if(status != 0)
printf("pthread2 is not created successfully!\n");
func_1 and func_2 are similar.
Then I want to dispatch them to different processors.So I use PTHREAD_SETAFFINITY_NP,but it failed.
My codes are below.
void func_1()
{
cpu_set_t mask1;
CPU_ZERO(&mask1);
CPU_SET(1,&mask1);
pthread_setaffinity_np(pthread_self(),sizeof(mask1),&mask1);
for (j = 0; j < cpu_num; j++) {
if (CPU_ISSET(j, &mask1))
{
//printf("thread %lld is running in processor %d\n", pthread_self(), j);
cout<<"thread "<<pthread_self()<<" is running in processor "<< j <<endl;
}
}
void func_2()
{
cpu_set_t mask2;
CPU_ZERO(&mask2);
CPU_SET(0,&mask2);
pthread_setaffinity_np(pthread_self(),sizeof(mask2),&mask2);
for (j = 0; j < cpu_num; j++) {
if (CPU_ISSET(j, &mask2))
{
//printf("thread %lld is running in processor %d\n", pthread_self(), j);
cout<<"thread "<<pthread_self()<<" is running in processor "<< j <<endl;
}
}
int main()
{
status1 = pthread_create(&pthread1,NULL,func_1,(void*)t1);
if(status1 != 0)
printf("pthread1 is not created sucessfully!\n");
status = pthread_create(&pthread2,NULL,func_2,(void*)t2);
if(status != 0)
printf("pthread2 is not created successfully!\n");
pthread_join(pthread1,NULL);
pthread_join(pthread2,NULL);
......
}
But to my surprised, result comes out like this:
thread 7369190208 is running in processor 0
thread 3065830208 is running in processor 0
How can I do to dispatch each thread to a specific processor?
EDIT:
I want to dispatch threads to different processors because if they two are running on one processor,it is like serial.How to dispatch?as shown below:
serial:
for(i = 0 ; i < N ; i ++)
do something;
I use two threads,then it becomes like:
pthread1:
for(i = 0 ; i < N ; i += 2)
do something;
pthread2:
for(i = 1 ; i < N ; i += 2)
do something;
and the speedup can be nearly 2

char in string is not in order wanted

I am a beginner and I need some help here. This program prints out the frequency of char in the string, e.g. if user enters zzaaa it prints out a3z2 and what I need to print is z2a3 since z is entered first before a. But I am having a hard time switching the order around. Thanks in advance!
int main
{
int ib, i=0, j=0, k=0;
int count[26] = {0};
char chh[3][10];
for (ib = 0; ib < 3; ib++) // get 3 input
gets(chh[ib]);
for (i = 0; i < 3; i++)
{
for (j = 0; j < 10; j++)
{
if (chh[i][j] >= 'a' && chh[i][j] <= 'z')
{
count[chh[i][j] - 'a']++;
}
}
for (k = 0; k < 26; k++)
{
if (count[k] != 0) // if array location is not equals to 0
printf("%c%d", k + 'a', count[k]);
}
memset(count, 0, sizeof(count)); //reset integer array
printf("\n");
}
It prints a before z because you arranged count from a to z by alphabetic priority not entering priority:
count[chh[i][j] - 'a']
if you want to print them by entering priority you should change it. there are several ways to do this. like this:
#include <stdio.h>
#include <string.h>
int main()
{
int ib, i=0, j=0,k=0, kk=0,c=0,found=0;
int count[26][2];
char chh[3][10];
for (ib = 0; ib < 3; ib++) // get 3 input
gets(chh[ib]);
printf("output is:\n");
for (i=0;i<26;i++)
{
count[i][0]=0;
count[i][1]=0;
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 10; j++)
{
if (chh[i][j] >= 'a' && chh[i][j] <= 'z')
{
found=0;
for (c=0;c<kk;c++)
if (count[c][0]==chh[i][j])
{
count[c][1]++;
found=1;
break;
}
if (!found)
{
count[c][0]=chh[i][j];
count[c][1]++;
kk++;
}
}
}
for (k = 0; k < 26; k++)
{
if (count[k][1] != 0) // if array location is not equals to 0
printf("%c%d", count[k][0], count[k][1]);
}
memset(count, 0, sizeof(count)); //reset integer array
printf("\n");
}
}

Resources