Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Программирование для Linux


Автор: GGoga 1.5.2007, 11:56
Здравствуйте, люди разбирающиеся в программировании для Linux. Помогите начинающему программисту разобраться в одной проблемке. Как можно программно реализовать задание, где необходимо вызвать системные команды используя execv, dup2. Примером является команда:
                            
tr -d "[0-9]" < a.txt | sort | uniq > b.txt 
Причем каждый системный вызов должен вызываться отдельно, т.е. execv("tr",{"tr","-d","[0-9]"}), затем execv("sort",{"sort"}) и execv("uniq",{"uniq"}). Но вот только эти три вызова должны работать на один результат, а именно, чтобы программа давала такой же результат, что и такая команда введенная в терминале.
И вообще, возможно ли так сделать??? Просто, я не пойму, как можно выполнить взаимодействие между разными процессами вызванными с execv, если они сами по себе не могут быть синхронизированы...
А с помощью одной команды execv делать нельзя по условию...

Люди, подскажите, кто хоть что-нибудь знает. Заранее ОГРОМНОЕ СПАСИБО smile

Автор: X-3R1 1.5.2007, 14:33
С одним exec всё работает, а с несколькими ...хех. Вообщем если найдёшь решение отпишись здесь, мне тоже интересно ;)

Автор: MAKCim 1.5.2007, 15:43
все просто, вот примерный алгоритм
Код

/*
 * @cmds: pointer to array of commands
 * @count: count of elements in `cmds'
 */
static int make_task(const char* cmds[], size_t count) {
    pid_t pids[MAX_PROCESSES_COUNT];
    size_t index;
    char *path;
    int pipe_fd[2] = {-1, -1},
         fd = -1;
    for (index = 0; index < count; ++index) {
        fd = *pipe_fd;
        pipe(pipe_fd); /* no error check */
        pids[index] = fork();
        if (pids[index] == 0) {
            if (fd < 0) {
                if ((path = parse(cmds[index], GET_IN_FILE)) != NULL)
                    fd = open(path, O_RDONLY); /* no error check */
                else goto output;
            }
            dup2(fd, STDIN_FILENO);
output:
            fd = -1;
            if (index < count - 1)
                fd = *(pipe_fd + 1);
            else if ((path = parse(cmds[index], GET_OUT_FILE)) != NULL)
                fd = open(path, O_WRONLY | O_CREAT | O_EXCL); /* no error check */
            dup2(fd, STDOUT_FILENO);
            pause(); /* wait for SIGUSR1 */
            /* make 'exec' for command with index `index' */
        } else if (pids[index] < 0) {
            /* error by creating process */
        }
        if (fd >= 0) close(fd);
        close(*(pipe_fd + 1));
    }
    while (count--)
        kill(pids[count], SIGUSR1); /* send SIGUSR1 to all created processes */
    return 0;
}

Автор: GGoga 2.5.2007, 14:50
Спасибо за примерчик!!! Ща буду разбираться smile

Автор: GGoga 6.5.2007, 14:42
Цитата(MAKCim @ 1.5.2007,  15:43)
все просто, вот примерный алгоритм
Код

/*
 * @cmds: pointer to array of commands
 * @count: count of elements in `cmds'
 */
static int make_task(const char* cmds[], size_t count) {
    pid_t pids[MAX_PROCESSES_COUNT];
    size_t index;
    char *path;
    int pipe_fd[2] = {-1, -1},
         fd = -1;
    for (index = 0; index < count; ++index) {
        fd = *pipe_fd;
        pipe(pipe_fd); /* no error check */
        pids[index] = fork();
        if (pids[index] == 0) {
            if (fd < 0) {
                if ((path = parse(cmds[index], GET_IN_FILE)) != NULL)
                    fd = open(path, O_RDONLY); /* no error check */
                else goto output;
            }
            dup2(fd, STDIN_FILENO);
output:
            fd = -1;
            if (index < count - 1)
                fd = *(pipe_fd + 1);
            else if ((path = parse(cmds[index], GET_OUT_FILE)) != NULL)
                fd = open(path, O_WRONLY | O_CREAT | O_EXCL); /* no error check */
            dup2(fd, STDOUT_FILENO);
            pause(); /* wait for SIGUSR1 */
            /* make 'exec' for command with index `index' */
        } else if (pids[index] < 0) {
            /* error by creating process */
        }
        if (fd >= 0) close(fd);
        close(*(pipe_fd + 1));
    }
    while (count--)
        kill(pids[count], SIGUSR1); /* send SIGUSR1 to all created processes */
    return 0;
}

Здравствуйте, MAKCim! Спасибо еще раз за Вашу помощь! Так как я начинающий программист и мне еще далеко не все понятно в программировании, у меня к Вам есть пару вопросов. Насколько я понимаю, в Вашем примере MAX_PROCESSES_COUNT, GET_IN_FILE и GET_OUT_FILE - это макроопределения или константы, скажите пожалуйста, чему они должны быть равны. А также, что делает функция parse? И последний вопрос, скажите пожалуйста, как правильно определить массив указателей, в котором будут храниться команды, т.е. елементом этого массива должна быть просто команда или команда с параметрами:
const char *cmds[] = {"tr", "-d \"[0-9]\"", "< a.txt", "sort", "uniq", "> b.txt"};
или
const char *cmds[] = {"tr -d \"[0-9]\" < a.txt", "sort", "uniq > b.txt"};
или как это должно быть правильно?

Заранее ОГРОМНОЕ СПАСИБО и извините за беспокойство!

Автор: MAKCim 6.5.2007, 16:01
Цитата(GGoga @  6.5.2007,  14:42 Найти цитируемый пост)
что делает функция parse?

получает на вход команду и возвращает NULL, если перенаправления ввода/вывода нет (т. е отсутствуют > и <)
иначе возвращает имя файла, куда перенаправляется ввод/вывод
GET_IN_FILE - означает поиск < 
GET_OUT_FILE - означает поиск >
функцию эту тебе самому придется написать  smile 
константы GET_IN_FILE, GET_OUT_FILE тоже нужно определить самостоятельно
Цитата(GGoga @  6.5.2007,  14:42 Найти цитируемый пост)
И последний вопрос, скажите пожалуйста, как правильно определить массив указателей, в котором будут храниться команды

все, что между |
т. е например для задачи 
Цитата

tr -d "[0-9]" < a.txt | sort | uniq > b.txt 

Код

const char *cmds[] = {"tr -d \"[0-9]\" < a.txt", "sort", "uniq > b.txt"};

Автор: GGoga 6.5.2007, 20:08
Спасибо за подсказку! smile

Автор: codelord 26.7.2007, 14:10
Цитата(MAKCim @  1.5.2007,  11:43 Найти цитируемый пост)
все просто, вот примерный алгоритм

сори за занудство, но мне так goto здесь лишнее
можно хотябы так:
Код

static int make_task(const char* cmds[], size_t count) {
    pid_t pids[MAX_PROCESSES_COUNT];
    size_t index;
    char *path;
    int pipe_fd[2] = {-1, -1},
         fd = -1;
    for (index = 0; index < count; ++index) {
        fd = *pipe_fd;
        pipe(pipe_fd); /* no error check */
        pids[index] = fork();
        if (pids[index] == 0) {
            if (fd < 0 && ((path = parse(cmds[index], GET_IN_FILE)) != NULL ) ) 
               {
                    fd = open(path, O_RDONLY); /* no error check */
               }
       else if( (fd > =0)  && !((path = parse(cmds[index], GET_IN_FILE)) != NULL) ) 
        { 
                  dup2(fd, STDIN_FILENO); 
        }
            fd = -1;
            if (index < count - 1)
                fd = *(pipe_fd + 1);
            else if ((path = parse(cmds[index], GET_OUT_FILE)) != NULL)
                fd = open(path, O_WRONLY | O_CREAT | O_EXCL); /* no error check */
            dup2(fd, STDOUT_FILENO);
            pause(); /* wait for SIGUSR1 */
            /* make 'exec' for command with index `index' */
        } else if (pids[index] < 0) {
            /* error by creating process */
        }
        if (fd >= 0) close(fd);
        close(*(pipe_fd + 1));
    }
    while (count--)
        kill(pids[count], SIGUSR1); /* send SIGUSR1 to all created processes */
    return 0;

не проверял

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