Вызов внешних программ
"The exec family of functions replaces the current process image with a new process image".
Отсюда вопрос: как вызвать внешнюю программу так, что бы текущий процесс продолжил своё выполнение?
С помощью функции exec(), никак. Функция exec() (execute) загружает и запускает другую программу. Таким образом, новая программа полностью замещает текущий процесс. Новая программа начинает свое выполнение с функции main. Все файлы вызывающей программы остаются открытыми. Они также являются доступными новой программе. Используется шесть различных вариантов функций exec.
int execl(char *name, char *arg0, ... /*NULL*/);
int execv(char *name, char *argv[]);
int execle(char *name, char *arg0, ... /*,NULL,
char *envp[]*/);
int execve(char *name, char *arv[], char *envp[]);
int execlp(char *name, char *arg0, ... /*NULL*/);
int execvp(char *name, char *argv[]);
Вызов exec происходит таким образом, что переданная в качестве аргумента программа загружается в память вместо старой, которая вызвала exec. Старой программе больше не доступны сегменты памяти, которые перезаписаны новой программой. Так что самой функцией этого не предусмотренно.
Но ....есть способ)) Можно создать новый процесс с помощью системного вызова fork(). Синтаксис вызова следующий:
#include <unistd.h>
pid_t fork(void);
pid_t является примитивным типом данных, который определяет идентификатор процесса или группы процессов. При вызове fork() порождается новый процесс (процесс-потомок), который почти идентичен порождающему процессу-родителю. Процесс-потомок наследует следующие признаки родителя:
* сегменты кода, данных и стека программы;
* таблицу файлов, в которой находятся состояния флагов дескрипторов файла, указывающие, читается ли файл или пишется. Кроме того, в таблице файлов содержится текущая позиция указателя записи-чтения;
* рабочий и корневой каталоги;
* реальный и эффективный номер пользователя и номер группы;
* приоритеты процесса (администратор может изменить их через nice);
* контрольный терминал;
* маску сигналов;
* ограничения по ресурсам;
* сведения о среде выполнения;
* разделяемые сегменты памяти.
При вызове fork() возникают два полностью идентичных процесса. Весь код после fork() выполняется дважды, как в процессе-потомке, так и в процессе-родителе.
Пример порождения процесса через fork() :
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
main()
{
pid_t pid;
int rv;
switch(pid=fork()) {
case -1:
perror("fork"); /* произошла ошибка */
exit(1); /*выход из родительского процесса*/
case 0:
printf(" CHILD: Это процесс-потомок!\n");
printf(" CHILD: Мой PID -- %d\n", getpid());
printf(" CHILD: PID моего родителя -- %d\n",
getppid());
printf(" CHILD: Введите мой код возврата
(как можно меньше):");
scanf(" %d");
printf(" CHILD: Выход!\n");
exit(rv);
default:
printf("PARENT: Это процесс-родитель!\n");
printf("PARENT: Мой PID -- %d\n", getpid());
printf("PARENT: PID моего потомка %d\n",pid);
printf("PARENT: Я жду, пока потомок
не вызовет exit()...\n");
wait();
printf("PARENT: Код возврата потомка:%d\n",
WEXITSTATUS(rv));
printf("PARENT: Выход!\n");
}
}
А так же------->>>>>>>
#include <stdio.h>
#include <unistd.h>
int main()
{
char pid{[}255{]};
fork();
fork();
fork();
sprintf(pid, "PID : %d\n",getpid());
write(STDOUT_FILENO, pid, strlen(pid));
exit(0);
}
В этом случае будет создано семь процессов-потомков. Первый вызов fork() создает первого потомка. Как указано выше, процесс наследует положение указателя команд от родительского процесса. Указатель команд содержит адрес следующего оператора программы. Это значит, что после первого вызова fork() указатель команд и родителя, и потомка находится перед вторым вызовом fork().После второго вызова fork() и родитель, и первый потомок производят потомков второго поколения - в результате образуется четыре процесса. После третьего вызова fork() каждый процесс производит своего потомка, увеличивая общее число процессов до восьми.
Ну вот и всё)) Думаю тебе немного нужно пересмотреть реализацию своей задачи, подход через exec() не верен! Удачи тебе прогер под Linux!!! ;)
одноранговых потомка
это как? :-\
if (f==NULL) exit;
char c;
while((c=fgetc(f))!= EOF)
cout<<c;
pclose(f);
непойдет?
С помощью execl не сможешь всё таки решить эту задачку)))
одноранговых потомка
это как? :-\
Это скорее от одного родителя :)
[quote]Цитата:
одноранговых потомка
это как? :-\ Это скорее от одного родителя [/quote]
Угу - помоему в литературе это так называлось...
Вобщем решил проблему тем же способом, что и описывал во втором посте. Никакого символа конца там дописывать не надо, всё и так уже продумано - просто кривые руки :)))
Если кому интересно - ниже код:
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
//-------------------------Global Variables--------------------------------
extern int errno;
bool signal_flag = false;
//-------------------------------------------------------------------------
//------------------------Auxilary functions-------------------------------
void onSignal( int )
{
signal_flag = true;
}
void echo( const char* const message, pid_t pid )
{
fprintf( stderr, "(debug message) Process %d sent message: %s\n", pid, message );
}
//-------------------------------------------------------------------------
int main( int argc, char** argv )
{
//Declare Variables
short int status, execute_status;
pid_t process_ls, process_grep, process_wc, process_common;
int pipeOne[ 2 ], pipeTwo [ 2 ], fp;
char *grepArgument;
//Declare Auxilary Variables
unsigned short int i;
int errCode;
//Initialize Variables
status = execute_status = 0;
char fileName[] = "a.txt";
errCode = 0;
//If any argument exists set it as grep parameter
if( argc > 1 )
grepArgument = argv[1];
else
{
grepArgument = (char*)malloc( strlen( "April" ) + 1 );
strcpy( grepArgument, "April" );
}
//Set signal catcher
signal( SIGUSR1, onSignal );
//Creating pipes (one per pipeline)
pipe( pipeOne );
pipe( pipeTwo );
//Creating childs. Let's each child get start after signal of preversion process (logical sequence)
//-------------------------------------------------------------------------------------------------
process_ls = fork();
if( process_ls == (pid_t)0 )
{
//-----------------------Body of child process---------------------------
//Print stats
echo( "Started...", getpid() );
//Set process output to pipeOne and close unusefull
close( pipeOne[ 0 ] );
close( pipeTwo[ 0 ] );
close( pipeTwo[ 1 ] );
close( STDOUT_FILENO );
dup( pipeOne[ 1 ] );
//Call to external program. Result will be redirected to pipeOne
errCode = execl( "/bin/ls", "ls", "-a", "-l", NULL );
if( errCode == -1 )
{
echo( strerror( errno ), getpid() );
kill( getppid(), SIGUSR1 );
execute_status = -1;
}
exit( execute_status );
//-----------------------------------------------------------------------
}
process_grep = fork();
if( process_grep == (pid_t)0 )
{
//-----------------------Body of child process---------------------------
//Print stats
echo( "Started...", getpid() );
//Set process input to pipeOne and process output to pipeTwo
close( pipeOne[ 1 ] );
close( pipeTwo[ 0 ] );
close( STDIN_FILENO );
dup( pipeOne[ 0 ] );
close( STDOUT_FILENO );
dup( pipeTwo[ 1 ] );
//Call to external program. Result will be redirected to pipeTwo
errCode = execl( "/bin/grep", "grep", grepArgument, NULL );
if( errCode == -1 )
{
echo( strerror( errno ), getpid() );
kill( getppid(), SIGUSR1 );
execute_status = -1;
}
exit( execute_status );
//-----------------------------------------------------------------------
}
process_wc = fork();
if( process_wc == (pid_t)0 )
{
//-----------------------Body of child process--------------------------
//Print stats
echo( "Started...", getpid() );
//Set process input to pipeTwo and output to file
close( pipeOne[ 0 ] );
close( pipeOne[ 1 ] );
close( pipeTwo[ 1 ] );
fp = open( fileName, O_WRONLY|O_CREAT );
close( STDIN_FILENO );
dup( pipeTwo[ 0 ] );
close( STDOUT_FILENO );
fcntl( fp, F_DUPFD, STDOUT_FILENO );
//Call to external program. Result will be redirected to pipeTwo
errCode = execl( "/usr/bin/wc", "wc", "-l", NULL );
if( errCode == -1 )
{
echo( strerror( errno ), getpid() );
kill( getppid(), SIGUSR1 );
execute_status = -1;
}
exit( execute_status );
//-----------------------------------------------------------------------
}
//-------------------------------------------------------------------------------------------------
//Close all relations with pipes
close( pipeOne[ 0 ] );
close( pipeOne[ 1 ] );
close( pipeTwo[ 0 ] );
close( pipeTwo[ 1 ] );
//Waiting for childs
while( ( process_common = wait(&status) ) > 0 )
{
//If error occured atleast in one child - terminate all application
if( signal_flag )
{
kill( -getpgrp(), SIGKILL );
execute_status = -1;
}
else
echo( "Finished...", process_common );
}
return( execute_status );
}
Ты также созжаёшь одноранговых потомков с помощью fork(), а уж потом и вызываешь с помощью execl() самих ls и grep ))))) :)