大家好,所以我的代码应该创建无限量的进程,每个进程运行自己的程序并传递投掷管道。
这是以递归方式完成的,这样第一个父项就会创建一个管道,然后是子项。在此之后,子项会创建一个pipe2和child2等....
问题是父进程不想等待创建所有子进程并且当我尝试插入时
waitpid(childpid, NULL, 0);
它有点永远等待......所以要么我想要最后一个孩子发送某种STOP WAIT信号,要么我想用另一种方法来解决这个问题!
以下是代码:
/* workForce.c
*
* Program created by ----Secret-----
*
* Input has to be the programs you wish the workForce to execute with following parameters seperated by '0's
*
* example input:
* printenv 0 grep L 0 sort
*
* Will result in the command: printenv | grep L | sort | chosen PAGER
*
* The program will pipe each unit of the workForce to the next unit untill it reaches the last unit where
* it will printout the result to STDOUT.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PIPE_READ_SIDE ( 0 )
#define PIPE_WRITE_SIDE ( 1 )
pid_t childpid; /* för child-processens PID vid fork() */
/*
* The generateWorkforce method automaticly creates it's own workforce with one process per taskset
* Each unit in the work force will execute the parameters provided
* As long as it's not the end of the workforce the unit will pipe its output to the next unit
*/
void generateWorkforce(int taskpointer, int totaltasks, int taskset[], char* tasks[]){
/* Create pipe then fork */
int pipe_filedesc[ 2 ];
int return_value;
return_value = pipe( pipe_filedesc );
if( -1 == return_value ) {perror( "Cannot create pipe" ); exit( 1 );}
childpid = fork();
if( 0 == childpid )
{
/* Redirecting STDIN to now read from pipe instead and removing the pipe */
return_value = dup2( pipe_filedesc[ PIPE_READ_SIDE], STDIN_FILENO );
if( -1 == return_value){perror( "Cannot dup" ); exit( 1 );}
return_value = close( pipe_filedesc[PIPE_READ_SIDE] );
if( -1 == return_value ){perror( "Cannot close read end" ); exit( 1 );}
return_value = close( pipe_filedesc[ PIPE_WRITE_SIDE ] );
if( -1 == return_value ){perror( "Cannot close write end" ); exit( 1 );}
if(taskpointer < totaltasks-1){
generateWorkforce((taskpointer+taskset[taskpointer]), totaltasks, taskset, tasks);
}
else {
kill(getppid, SIGINT);
execlp(tasks[taskpointer], tasks[taskpointer], (char *) 0);
/* exec only returns if an error occured */
perror( "Cannot exec execute[pointer]" );
exit( 1 );
}
}
else
{
if( -1 == childpid ){ perror( "Cannot fork()" ); exit( 1 );}
/* Redirecting STDOUT to write to pipe instead and thereafter removes the pipe */
return_value = dup2( pipe_filedesc[ PIPE_WRITE_SIDE], STDOUT_FILENO );
if( -1 == return_value){perror( "Cannot dup" ); exit( 1 );}
return_value = close( pipe_filedesc[ PIPE_WRITE_SIDE ] );
if( -1 == return_value ){perror( "Cannot close write end" ); exit( 1 );}
return_value = close( pipe_filedesc[ PIPE_READ_SIDE ] );
if( -1 == return_value ){perror( "Cannot close read end" ); exit( 1 );}
waitpid(childpid, NULL, 0);
/* Will define what task to execute and how many parameters it needs */
if(taskset[taskpointer] > 1){
char* execute[taskset[taskpointer]+1];
int i;
char* executeHead = tasks[taskpointer];
execute[0] = tasks[taskpointer];
for(i = 1;i<taskset[taskpointer];i++){
execute[i] = tasks[taskpointer+i];
}
execute[taskset[taskpointer]] = (char *) 0;
(void) execvp( executeHead, execute );
}
else{
(void) execlp( tasks[taskpointer], tasks[taskpointer], (char *) 0 );
}
/* exec only returns if an error occured */
perror( "Cannot exec tasks[taskpointer]" );
exit( 1 );
}
}
int main( int argc, char * argv[] )
{
/* The following block will determine how many tasksets was in the input */
char * separator = "0";
int i;
int j;
int tasknr = 1;
for(i = 1, j = 1;i<(argc);i++)
{
if(!(strcmp(argv[(i)], separator ))){
j++;
}
else{
tasknr++;
}
}
char* execute[tasknr];
int taskset[j+1];
/* Will fill the taskset array and execute array */
if(getenv("PAGER")) execute[(tasknr-1)] = getenv("PAGER");
else execute[(tasknr-1)] = "less";
taskset[j] = 1;
taskset[0] = 0;
int k = 0;
for(i = 1, j = 0;i<(argc);i++)
{
if(!(strcmp(argv[(i)], separator ))){
j++;
taskset[j] = 0;
}
else{
execute[k] = argv[i];
taskset[j]++;
k++;
}
}
generateWorkforce(0, tasknr, taskset, execute);
exit( 0 );
}
编辑:kill(getppid,SIGINT);试图阻止等待!
答案 0 :(得分:2)
正如我们在评论中所说,您需要使用信号量并在两个过程之间实现同步。
信号量可以计数,但也可以是二进制。有关POSIX信号量的更多信息,here。
您需要创建的内容称为流程链,可以通过循环轻松制作,如@ J.F.Sebastian所述。
您已经要求使用POSIX信号量,但要注意POSIX IPC并非在所有系统中完全实现,因为SystemV是。
一些信息:
当进程分叉时,其内存将被复制到新进程的内存段。
如果你想使用sem_init(未命名的信号量)的信号量,你将不得不使用shm_open,mmap和shmget来
将信号量放在共享内存区域,以便两个进程可以正确使用它。
您可以(并且应该)阅读所有相关信息here和here。
为了简化我的解决方案,我使用了一个名为sema_ore的命名信号量。
我首先创建信号量并使用value == 0
初始化它,然后使用循环,所有需要的进程都是分叉的。
由pid标识的主要进程被sem_wait
电话阻止。
现在,最后一个孩子通过sem_post
调用通知主进程已创建它。
以下是实现所有这些的代码:
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/file.h>
#include <errno.h>
#define PROCS_NO 3
#define chneg(r,s) { if (r < 0) {perror(s); exit(EXIT_FAILURE);}}
int main(void)
{
//check argument count
//check input, for the sake of simplycity I'll use a #defined value
pid_t childpid = 0;
int i;
sem_t* sem;
pid_t mainproc = getpid();
sem = sem_open("notify", O_CREAT | O_EXCL, 0644, 0);
/* name of semaphore is "notify", semaphore is reached using this name */
chneg(sem_unlink("notify"), "sem_unlink");
/* unlink prevents the semaphore existing forever */
/* if a crash occurs during the execution */
for (i = 0; i < PROCS_NO; i++)
{
sleep(1);
printf("\nAbout to create child %d\n", i);
childpid = fork();
if (childpid < 0) {
perror("Fork error"); return -1;
}
if (childpid == 0) {
//child process, continue the loop
}
else
break; //parent process, exit the loop
}
if (getpid() == mainproc) {
//main process must wait for the last process to be created
chneg(sem_wait(sem), "sem_wait");
printf("\nMain Process: Just woke up\n");
/* cleanup semaphores */
chneg(sem_destroy (sem), "sem_destroy");
exit (0);
}
else {
//child processes
if (i == PROCS_NO -1 )
{
printf("\nLast child, going to sleep for 3\"\n");
sleep(3);
printf("\nJust woke up, waking up, main process as well\n");
chneg(sem_post(sem), "sem_post");
int semval;
chneg(sem_getvalue(sem, &semval), "getvalue");
printf("\nExiting with sem == %d\n", semval);
}
exit (0);
}
}