LINUX.ORG.RU

100% загрузка CPU при выводе в XTerm


0

0

Здравствуйте. Пытаюсь разобраться, как можно использовать xterm для своих нужд, нужен вывод текста в консольв X-ах. Набросал простенький пример.

using namespace std;

int clone_xterm(void* pPtr)
{
    cout << "create xterm process..." << endl;
    int l_fID = open("/tmp/xterm_file", O_CREAT | O_RDONLY | O_NONBLOCK, S_IREAD| S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH);
    cout << "open file /tmp/xterm_file with ID = " << l_fID << endl;
    stringstream l_ss;
    l_ss << "-Sxt/" << l_fID;
    if (execlp("xterm", "xterm", l_ss.str().c_str(), NULL) == -1)
    {
        cout << "create xterm proces filed :(" << endl;
    }
    else
        cout << "xterm created :)" << endl;
    close(l_fID);
    return 0;
}

int main()
{
    void *l_pstack = malloc(1048576);
    char *l_p = (char*)l_pstack + 1048575;
    char *l_pStr = (char*)"test\n\r";
    int l_fID = open("/tmp/xterm_file", O_CREAT | O_WRONLY | O_NONBLOCK | O_TRUNC, S_IREAD| S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH);
    pid_t l_pXterm = (pid_t)clone(&clone_xterm, (void*)l_p, 0, NULL);
    int i = 0;
    while (i < 10)
    {
        sleep(1);
        cout << "i = " << i << endl;
        write(l_fID, (void*)l_pStr, strlen(l_pStr));
        i++;
    }
    kill(l_pXterm, SIGQUIT);
    close(l_fID);
    remove("/tmp/xterm_file");
    free(l_pstack);
    return 0;
}

Все работает, но проблема в том, что пока открыто второе окно xterm (созданное через execlp() и в котором отражаются выводимые строки) загрузка процессора составляет 100%. Как только комментирую ключ запуска -Sccn нагрузка на процессор обычная. Как этого можно избежать, или, что я делаю не правильно?

ASP14 (FC9) + GCC4.3.2 + xterm (241)

Заранее благодарю за ответы.

P.S. на стиль кода прошу не смотреть ибо пример «написан на коленке», что бы понять «как оно работает».


> P.S. на стиль кода прошу не смотреть ибо пример "написан на коленке", что бы понять "как оно работает".

странная у вас манера писания на коленке, вместо того, что-бы написать 6 символов - fork(), наваяли огород с clone :) И спрашивается "для чего" ? Можно тот-же vfork() как более экономичную обертку к clone, чем fork(). Разницы я думаю никто не заметит :)

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

fork/vfork не подходят, если я правильно понимаю. Для их применения мне нужно править main() чтобы различать что сейчас запущено родитель или потомок, а как-либо изменять main() нельзя. Поэтому и выбрал clone(), т.к. при pthread_create() и т.д. вызов execlp() приостанавливает работу всего приложения. А через clone() я создаю по сути то же, что и при fork(), но и не лезу в main().

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

эээ... вообще ниче не понял. Вы че-та путаете теплое и мягкое.
 К тому-же вот такой аналог clone можно написать на обычном fork-е:

int my_clone(void (*fn)())
{
        int fr = fork();
        if (fr == 0)
        {
                fn(); 
                exit(0);
        }
        return fr != -1? 0 : -1;          
}

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

Оказалось, это я не правильно понял маны и примеры. Посчитал, что fork() для потомка передает управление функции main().

Переписал на fork(), проблема ни куда не делась :)
Если комментирую ключ -Sccn то нагрузки на процессор ни какой, убераю комментарий и поучаю 100% звгрузку
using namespace std;

int clone_xterm()
{
    cout << "create xterm process..." << endl;
    int l_fID = open("/tmp/xterm_file", O_CREAT | O_RDONLY /*| O_NONBLOCK*/, S_IREAD| S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH);
    cout << "open file /tmp/xterm_file with ID = " << l_fID << endl;
    stringstream l_ss;
    l_ss << "-Sdo/" << l_fID;
    if (execlp("xterm", "xterm", "-title", "Debug output", "-name", "Debug output", l_ss.str().c_str(), NULL) == -1)
    {
        cout << "create xterm proces filed :(" << endl;
    }
    else
        cout << "xterm created :)" << endl;
    close(l_fID);
    exit(0);
}

int main()
{
    char *l_pStr = (char*)"test\n\r";
    int l_fID = open("/tmp/xterm_file", O_CREAT | O_WRONLY /*| O_NONBLOCK */| O_TRUNC, S_IREAD| S_IWRITE | S_IRGRP | S_IWGRP | S_IROTH);
    cout << "Hello World" << endl;
    pid_t l_pXterm = fork();
    if (l_pXterm == 0)
        clone_xterm();
    int i = 0;
    while (i < 10)
    {
        sleep(1);
        cout << "i = " << i << endl;
        write(l_fID, (void*)l_pStr, strlen(l_pStr));
        i++;
    }
    kill(l_pXterm, SIGQUIT);
    close(l_fID);
    remove("/tmp/xterm_file");
    return 0;
}

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

А теперь внимание вопрос: какой процесс собственно жрет проц? xterm или a.out? (top-ом посмотреть не?)

Вопрос N2: почему вы решили что это вообще будет работать? обьясните на пальцах, то, как должно это работать.

Я лично подозреваю, что xterm хочет что-бы то, что ему подсовывают в качестве терминала (в данном случае - /tmp/xterm_file) поддерживало набор некоторых tty/pty специфичных ioctl-ей, и умело делать select, для ожидания активности на терминале (select на regular файле всегда возвращает сразу), вот и крутится внутри него в бешенном цикле select.

По сабжу: то, что вы хотите сделать, imho разумнее всего сделать запустив в новом терминале команду tail -f /tmp/xterm_file, и все...

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

Огромное спасибо за подсказку про select(), как-то не подумал сам про это. В итоге просто объявил файл FIFO через mkfifo() и все заработало как надо.

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