Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C] Создание процессов


Автор: DeathKnight 8.9.2010, 16:24
необходимо написать программу, которая создает два процесса. те, в свою очередь, должны выводить системное время в разных углах консольного окна.
реализовать надо под винду и линукс.
вопрос такой: в какую сторону копать, какие нужны ф-ии и какие есть нюансы?
заранее благодарю.

Автор: djamshud 8.9.2010, 16:27
Linux: fork для создания дочернего процесса-себя-же, ncurses для рисования в консоли. Если хочется запустить совсем другой процесс, то fork+execv.

Добавлено через 50 секунд
Нюанс есть: заставить два процесса рисовать в одну консоль.

Автор: ller 10.9.2010, 20:45
Процессы или потоки?

Автор: DeathKnight 10.9.2010, 21:01
Цитата(ller @ 10.9.2010,  20:45)
Процессы или потоки?

Цитата

Процессы или потоки?


процессы.

Код

#include <windows.h>
#include <iostream>
#include <iomanip>
#include <TCHAR.h>
#include <time.h>
#include <conio.h>



using namespace std;

int _tmain( int argc, TCHAR *argv[] )
{
    int temp;
    STARTUPINFO si1, si2;
    PROCESS_INFORMATION pi1, pi2;
    TCHAR *pi1cl;
    TCHAR *pi2cl;
    ZeroMemory( &si1, sizeof(si1) );
    ZeroMemory( &si2, sizeof(si2) );
    si1.cb = sizeof(si1);
    si2.cb = sizeof(si2);
    ZeroMemory( &pi1, sizeof(pi1) );
    ZeroMemory( &pi2, sizeof(pi2) );

    if( argc < 2 )
    {
        pi1cl=(TCHAR*)calloc(4, sizeof(TCHAR));
        lstrcpy(pi1cl, L"1");
        /*
        si1.dwX = 0;
        si1.dwY = 0;
        si1.dwXCountChars = 40;
        si1.dwYCountChars = 25;
        si1.dwFlags = STARTF_USEPOSITION | STARTF_USECOUNTCHARS;
        */
        temp=CreateProcess( 
             argv[0],                // No module name (use command line)
             pi1cl,                    // Command line
             NULL,                    // Process handle not inheritable
             NULL,                    // Thread handle not inheritable
             FALSE,                    // Set handle inheritance to FALSE
             0, //CREATE_NEW_CONSOLE,    
             NULL,                    // Use parent's environment block
             NULL,                    // Use parent's starting directory 
             &si1,                    // Pointer to STARTUPINFO structure
             &pi1 );
        if( !temp) 
        {
            cout << "CreateProcess failed.\n" << endl;
            return 0;
        }else
        {
            cout << "Process 1 created" << endl;
        }
                
        pi2cl=(TCHAR*)calloc(4, sizeof(TCHAR));
        lstrcpy(pi2cl, L"2");
        /*
        si2.dwX = 41;
        si2.dwY = 0;
        si2.dwXCountChars = 40;
        si2.dwYCountChars = 25;
        si2.dwFlags = STARTF_USEPOSITION | STARTF_USECOUNTCHARS;
        */
        if( !CreateProcess( 
             argv[0],                // No module name (use command line)
             pi2cl,                    // Command line
             NULL,                    // Process handle not inheritable
             NULL,                    // Thread handle not inheritable
             FALSE,                    // Set handle inheritance to FALSE
             0, //CREATE_NEW_CONSOLE,
             NULL,                    // Use parent's environment block
             NULL,                    // Use parent's starting directory 
             &si2,                    // Pointer to STARTUPINFO structure
             &pi2 )                    // Pointer to PROCESS_INFORMATION structure
            ) 
        {
            printf( "CreateProcess failed.\n", GetLastError() );
            TerminateProcess((HANDLE)pi1.dwProcessId, 0);
            return 0;
        }else
        {
            cout << "Process 2 created" << endl;
        }

        HANDLE piMas[2];
        piMas[0]=(HANDLE)pi1.dwProcessId;
        piMas[1]=(HANDLE)pi2.dwProcessId;

        //WaitForMultipleObjects(2, piMas, true, INFINITE);
        WaitForSingleObject((HANDLE)pi1.dwProcessId, INFINITE);

        CloseHandle( pi1.hProcess );
        CloseHandle( pi1.hThread );
        cout << "First process closed." << endl;
        CloseHandle( pi2.hProcess );
        CloseHandle( pi2.hThread );
        cout << "Second process closed." << endl;
        
        system("pause");
        return 0;
    }
    else
    {
        if(!lstrcmp(argv[1], L"1"))
        {
            char timestr[10];
            do
            {
                _strtime_s( timestr, 9 );
                cout << setiosflags(ios::left) 
                     << timestr
                     << resetiosflags(ios::left) << endl;
                Sleep(700);
            }while(!_kbhit());
        }

        if(!lstrcmp(argv[1], L"2"))
        {
            char timestr[10];
            do
            {
                _strtime_s( timestr, 9 );
                cout << setiosflags(ios::right) 
                     << setw(39)
                    << timestr
                     << resetiosflags(ios::right) << endl;
                Sleep(700);
            }while(1);
        }
    }
    return 0;
}



вот набросал код для win, но найти ошибки не могу. что я упустил?

Автор: DeathKnight 10.9.2010, 21:24
Цитата(djamshud @  8.9.2010,  16:27 Найти цитируемый пост)
Нюанс есть: заставить два процесса рисовать в одну консоль. 


как это можно сделать?

Автор: ИванМ 12.9.2010, 20:06
Цитата(DeathKnight @  10.9.2010,  21:24 Найти цитируемый пост)
как это можно сделать? 

Смотри в сторону синхронизации. В инете на эту тему много инфы.
На счет ошибки, то скажи какая конкретно.

Автор: DeathKnight 13.9.2010, 11:35
в общем вот:
под линь:
Код

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <time.h>

int main(void)
{
 initscr();
 clear();
 refresh(); 
 pid_t cpid=fork(); 

 if(cpid==0)
 {    
    do
    {
    time_t t = time(NULL);
    char* s=ctime(&t);
    mvaddstr(0,0,s);
    refresh();    
    }
    while(1);
  }
  else 
  {    
    do
    {
    time_t t = time(NULL);
    char* s=ctime(&t);
    mvaddstr(0,40,s);
    refresh();    
    }
    while(1);
  };
return 1;
}


и под винду:
Код

#include <windows.h>
#include <iostream>
#include <iomanip>
#include <TCHAR.h>
#include <time.h>
#include <conio.h>

using namespace std;

int _tmain( int argc, TCHAR *argv[] )
{
    int temp;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    si.cb = sizeof(si);
    TCHAR picl[100];
    ZeroMemory(&picl, 100);

    temp = (int)CreateMutex(NULL, FALSE, L"8e07e18e-11e8-4e48-9c08-cc91d05f6ad8");
    temp = GetLastError();
    if(temp == ERROR_ALREADY_EXISTS || temp == ERROR_ACCESS_DENIED)
    {
        char timestr[10];
        COORD ch;
        ch.X=0;
        ch.Y=0;
        do
        {
            temp = (int)GetConsoleWindow();
            SetConsoleCursorPosition((HANDLE)temp, ch);
            _strtime_s( timestr, 9 );
            cout << setiosflags(ios::left)
                 << "child process: "
                 << timestr
                 << resetiosflags(ios::left) << endl;
            Sleep(700);
        }while(!kbhit());
        return 0;
    }
    else
    {
        temp = CreateProcess(argv[0], picl, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi);
        if(temp != 0)
        {
            char timestr[10];
            COORD pr;
            pr.X=40;
            pr.Y=0;
            do
            {
                    temp = (int)GetConsoleWindow();
                    temp = SetConsoleCursorPosition((HANDLE)temp, pr);
                    _strtime_s( timestr, 9 );
                    cout << setiosflags(ios::right) 
                         << setw(60)
                         << "parent process: "
                         << timestr
                         << resetiosflags(ios::right) << endl;
                    Sleep(600);
            }while(!kbhit());
        }
        else return 0;
        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hProcess);

    }
    return 0;
}


в общем все работает. но не разобрался с выводом под винду. там не получается установить курсор, в итоге вместо одной строки получается последовательность.

Автор: DeathKnight 17.9.2010, 23:09
теперь сделал нормально. если кому будет нужно:
Код

#include <windows.h>
#include <TCHAR.h>
#include <time.h>
#include <stdio.h>
#include <conio.h>

int _tmain( int argc, TCHAR *argv[] )
{
    int temp;                                        // переменная для получения кодов ошибок
    HANDLE mutex;                                    // дескриптор мьютекса
    STARTUPINFO si;                                    // окружение для дочернего процесса
    PROCESS_INFORMATION pi;                            // описание процесса дочернего процесса
    ZeroMemory(&si, sizeof(si));                    // очистка структур
    ZeroMemory(&pi, sizeof(pi));
    si.cb = sizeof(si);
    TCHAR picl[100];
    ZeroMemory(&picl, 100);
    HANDLE hInput, hOutput;

    mutex = CreateMutex(NULL, FALSE, L"8e07e18e-11e8-4e48-9c08-cc91d05f6ad8"); // создание именного объекта мьютекса
    temp = GetLastError();
    if(temp == ERROR_ALREADY_EXISTS || temp == ERROR_ACCESS_DENIED)               // цикл работы дочернего процесса
    {
        char timestr[10];
        COORD ch;
        ch.X=0;
        ch.Y=0;
        do
        {
            temp = WaitForSingleObject(mutex, INFINITE);                       // ожидание и получение доступа к мьютексу
            switch(temp)
            {
                case WAIT_OBJECT_0:                                               // доступ получен    
                    {
                        hInput = GetStdHandle(STD_INPUT_HANDLE); 
                        hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
                        _strtime_s( timestr, 9 );
                        SetConsoleCursorPosition(hOutput,ch);
                        printf("child process: %s", timestr);
                        Sleep(500);
                        ReleaseMutex(mutex);
                        break;
                    }
            }
        }while(!_kbhit());
        CloseHandle(mutex);
        return 0;
    }
    else        // родительский цикл
    {
        temp = CreateProcess(argv[0], picl, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi); // создание дочернего процесса
        if(temp != 0)
        {
            char timestr[10];
            COORD pr;
            pr.X=40;
            pr.Y=0;
            do
            {
                temp = WaitForSingleObject(mutex, INFINITE);
                switch (temp)
                {
                    case WAIT_OBJECT_0:
                        {
                            hInput = GetStdHandle(STD_INPUT_HANDLE); 
                            hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
                            _strtime_s( timestr, 9 );
                            SetConsoleCursorPosition(hOutput, pr);
                            printf("parent process: %s", timestr);
                            ReleaseMutex(mutex);
                            Sleep(500);
                            break;
                        }
                }
            }while(!_kbhit());
        }
        else return 0;
        WaitForSingleObject(pi.hProcess, INFINITE);            // ожидание завершения дочернего процесса
        CloseHandle(pi.hProcess);                            // закрытие дескрипторов объектов ядра
        CloseHandle(mutex);
    }
    return 0;
}


Код

#include <time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <curses.h>
#include <unistd.h>
#include <signal.h>

void sig_winch(int signo)                                // обработка сигнала изменения окна
{
    struct winsize size;                                // структура "размер окна"
    ioctl(fileno(stdout), TIOCGWINSZ, (char *) &size);  // получение данных о новых размерах окна
    resizeterm(size.ws_row, size.ws_col);                // обновление содержимого окна в соответствии с новыми размерами
}

void win_draw(WINDOW * pwnd, int row, int col)            // вывод в опр. окно в опр. координаты
{
    WINDOW *wnd;                                        // дескриптор окна
    wnd = derwin(pwnd, 5, 30, row, col);                // создание под-окна
    wrefresh(wnd);                                        // обновление под-окна

    time_t _time = time(NULL);                            // получение времени
    char * _ctime = ctime(&_time);                        // формирование строки
    mvwaddstr(wnd, 0, 0, _ctime);                        // вывод строки в под-окно
    delwin(wnd);    
    sleep(0.4);
}

int main()
{
    WINDOW * wnd;                                     // дескриптор окна терминала
    bool temp;                                            
    wnd = initscr();                                    // инициализация библиотеки
    signal(SIGWINCH, sig_winch);                        // установка обработчика сигнала
    cbreak();                                            // ввод с клавиатуры моментальный, не дожидаясь ENTER
    attron(A_UNDERLINE);                                // установка параметров текста, подчеркнутый
    curs_set(0);                                        // "выключение" курсора
    clear();                                            // очистка экрана
    refresh();                                            // вывод изменений
    
    pid_t _pid = fork();                                // порождение дочернего процесса
    if (_pid != -1)
    {    
        while(1)
        {
            if (_pid)                                    // если родительский
            {
                if(!temp)
                {
                    sleep(1);
                    temp=true;
                }
                win_draw(wnd, 0, 45);
                sleep(0.1);
            }
            else                                        // дочерний
            {    
                win_draw(wnd, 0, 0);
            }
        }
        if (_pid)
        {
            kill(_pid, SIGKILL);                        // убийство дочернего
        }
    }
    else
    {
        printf("Occured fork()-error");
    }
    endwin();                                            // очистка параметров библиотеки
    system("clear");                                    // чистка экрана системными ф-ями
    return 0;
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)