LINUX.ORG.RU

проблема с execv


0

0

Здравствуйте! У меня такая проблема: Из одной программы я вызываю другую. Вот из которой вызываю:

#include <unistd.h> 
#include <stdio.h> int main (void) { 

char *arg[] = { "/home/pasha/Документы/1", 0 }; 

/* fork, and exec within child process */ 
if (fork() == 0) 
{ 
printf("In child process:\n"); 
execv(arg[0], arg); 
printf("I will never be called\n"); 
}
printf("Execution continues in parent process\n"); }
А вот которую вызываю:
#include <termios.h> 
#include <sys/ioctl.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <curses.h> 
#include <time.h> 
#include <sys/time.h> 
void alarm_handler() 
{ 
int i; 
time_t tp; 
char *s; 
tp = time(NULL); 
s = ctime(&tp); 
wprintw(stdscr,"%s",s); 
refresh(); 
} 

int main(int argc, char * argv[]) 
{ 
struct itimerval delay; 
int ret; 
int y; 
if(argc>1) 
y=(int)argv[1]; 
signal (SIGALRM, alarm_handler); 
delay.it_value.tv_sec = 3; 
delay.it_value.tv_usec = 0; 
delay.it_interval.tv_sec = 1; 
delay.it_interval.tv_usec = 0; 
ret = setitimer (ITIMER_REAL, &delay, NULL); 

initscr(); 
curs_set(TRUE); 
while(1) 
{
 move(3,1); 
pause(); 
} 
endwin(); 
exit(EXIT_SUCCESS); 
} 
В этой выводится время. Как я понимаю эта должна выполниться и вернуть управлению в первую и на экране должно появиться Execution continues in parent process. А у меня получается наоборот сначала выводится эта надпись, а потом выводится таймер и терминал начинает подглючивать. Поясните пожалуйста в чем проблема.


да "одновременно".

bymer
() автор топика

> Как я понимаю эта должна выполниться и вернуть управлению в первую и на экране должно появиться Execution continues in parent process. А у меня получается наоборот сначала выводится эта надпись, а потом выводится таймер и терминал начинает подглючивать. Поясните пожалуйста в чем проблема.

В соседнем топике писал. Нет, никто никого ждать не будет, если ты явно этого не попросишь. Родитель и ребёнок выполняются одновременно.

См. wait(2)

kemm
()

fork() создаёт новый процесс, поэтому управление остаётся у родительской программы, параллельно начинает выполняться дочерняя программа.

roy ★★★★★
()
Ответ на: комментарий от roy

Мне нужно чтобы таймер шел, а родительский процесс продолжал своё выполнение. Как Вы писали что после fork() процессы начинают параллельно работать, то в данном случае у меня получилось, что потомок работает(выводит таймер), а родительский ничего не делает так как вывел нужное сообщение. Я прав?

bymer
() автор топика
Ответ на: комментарий от bymer

Если прав, то я не понимаю почему тогда, если заменить программу из которой я вызываю на эту:

#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <termios.h>
#include <sys/ioctl.h>

#define MAXFORK 30

int next_y;
int koord_y;

struct result
{
	int caseNumber;
	int argument;
};

struct process
{
	int  pid;
	char name[20];
	bool isPaused;
};
process *procs;

int mygetch()
{
	struct termios oldt, newt;
	int ch;
	tcgetattr(STDIN_FILENO, &oldt);
	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);
	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
	ch=getchar();
	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
void drawLines()
{
	clear();
	refresh();
	int i;
	int x,y;
	
	y = 1;
	x = COLS;
	move(1,0);
	for(i = 0; i < LINES-1; i++)
	{
		move(y,0);
		wprintw(stdscr,"|");
		move(y,x-1);
		wprintw(stdscr,"|");
		move(y,x-20);
		if(i+5<LINES)
			wprintw(stdscr,"|");
		y++;
	}
	move(0,0);
	for(i = 0; i < COLS; i++)
		wprintw(stdscr,"-");
	move(2,1);
	for(i = 0; i < COLS-21; i++)
		wprintw(stdscr,"-");
	move(LINES-5,0);
	for(i = 0; i < COLS; i++)
		wprintw(stdscr,"-");
	move(LINES-1,0);
	for(i = 0; i < COLS; i++)
		wprintw(stdscr,"-");
	
	move(LINES-3,2);
	wprintw(stdscr,"cmd:");
	refresh();
}

void drawProcs(process *names)
{
	int y = 1;
	int x = COLS-19;
	int i=0;
	char *s;
	time_t tp;
	for(;i<MAXFORK;i++)
	{
		if(names[i].pid)
		{
			move(y,x);
			wprintw(stdscr,"%s",names[i].name);			
			y++;
		}	
	}
}


void signal_handler(int signum)
{
 refresh();
  move(1,1); 
  wprintw(stdscr,"process %d",next_y+1);
  refresh();
  usleep(200000);
  move(1,1); 
  wprintw(stdscr,"          ");
  refresh();

}

int addProcess()
{
		int w;
	int pid = fork();
	if(pid == -1)
		exit(1);
	if(pid == 0)
	{
		w=execl("/home/pasha/Документы/1", "1",(char*)0);
		sigset_t sig_mask;
		struct sigaction act;
		sigemptyset(&sig_mask);
		act.sa_mask = sig_mask;
		act.sa_flags = 0;
		act.sa_handler = &signal_handler;
		sigaction(SIGUSR1,&act,NULL);
		while(1)
		{

			pause();
			kill(getppid(),SIGUSR1);
		}
				
	}
	else
		return pid;
	koord_y++;
	return 0;
}

void init_screen()
{
	initscr();
	echo();
    curs_set(1);
}

void clearCMD()
{
	move(LINES-3,6);
	clrtoeol();
	refresh();
	move(LINES-3,7);
}
void nothing(int sig)
{}

int main()
{ 
	int ret;
	procs = (process*)calloc(MAXFORK,sizeof(process));
	koord_y = 1;
	sigset_t sig_mask;  
	struct sigaction act;
	act.sa_handler = &nothing;
	sigemptyset(&sig_mask);
	act.sa_mask = sig_mask;
	act.sa_flags = 0;
	sigaction(SIGUSR1,&act,NULL);

    	init_screen();    
        
		
		int count = 0;
		int  i;
        char cmd[50],namebuf[20];
        
        int key;
        result res;
        
        drawLines();
        clearCMD();

        while(1)
        {  
        key = mygetch();
        switch(key)
	{
		case 'c': for(i=0;procs[i].pid !=0 ; i++);
        		next_y = i;
        		move(1,1);
				procs[i].pid = addProcess();
				procs[i].isPaused = false;
				sprintf(procs[i].name,"pid %d | active",procs[i].pid);
				count++;
			 break;
		case '0': ;
		case '1': ;
		case '2': ;
		case '3': ;
		case '4': ;
		case '5': ;
		case '6': ;
		case '7': ;
		case '8': ;
		case '9': 	int k = (int) key - 49;
        		
        				if(procs[k].isPaused == false)
        				{
        					procs[k].isPaused = true;
        					sprintf(procs[k].name,"pid %d | paused",procs[k].pid);	
        				}
        				else
        				{
        					procs[k].isPaused = false;
        					sprintf(procs[k].name,"pid %d | active",procs[k].pid);	
        				}
        			
			
 break;
	}
        	move(1,1);
        	refresh();      	
        	for(i = 0 ; i < MAXFORK ; i++)
        	if(procs[i].pid)
        	{
        		if(procs[i].isPaused == false)
        		{
        			kill(procs[i].pid,SIGUSR1);
        			pause();
        		}
        	}
        	
        	drawLines();
        	drawProcs(procs);
        	clearCMD();
        	cmd[0] = '\0';		      	  	
        }             
        endwin();
}

Почему тогда после выполнения и нажатия клавиши «c» курсор зависает на экране с надписью «|» и ничего больше нажать нельзя - помогает только CTRL-C. А нужно чтобы шло время. Подскажите пожалуйста в чем я не прав?

bymer
() автор топика
Ответ на: комментарий от bymer

Разбираться в вашем коде нет возможности. Что делает родительский процесс? Что делает дочерний процесс? После форка нельзя сказать, кто из процессов первым выведет своё сообщение на консоль, т.к. управление может перейти к любому из них. И в дальнейшем управление будет прыгать с процесса на процесс. Если оба процесса работают с терминалом, то глюки обеспечены. Если вам нужна как-то синхронизировать их работу — смотрите в сторону примитивов синхронизации. Но сперва поясните, какая работа выполняется в родительском процессе после форка, и какая — в дочернем.

roy ★★★★★
()
Ответ на: комментарий от bymer

Что должна делать конструкция "for(i=0;procs[i].pid !=0 ; i++);" ?

И, не принято делать операции ввода/вывода, и тем более usleep() в обработчике сигналов. Там только выставляются флажки и всё.

Не нужно мешать в кучу curses и tcsetattr. Перед fork() лучше маскровать все сигналы, чтобы потомок, не ушёл в обработчик сигнала родителя.

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.