LINUX.ORG.RU

Передача параметров командной строки при fork() возможна?

 ,


0

1

Добрый вечер. Sorry за глупый вопрос, вычитал что прототип для fork() выглядит так:

pid_t fork(void);
А void, если я правильно понимаю, чаще означает «необязательно» чем «отсутствует». Значит ли это, что через fork() можно передать параметр для «потомка»? Пробовал так:
fork("1");
и так:
fork(1);
В обоих случаях потомок создается, но в выводе ps -ax |grep MyProgram значилось просто 2 экземпляра моей наколенки, без параметра.

Собственно вопрос: можно ли выполняя fork() явным образом указать параметры ком.строки, что бы было видно потом их в списке процессов?



Последнее исправление: CYB3R (всего исправлений: 1)

зачем?

у порождённого процесса и так будет копия всех переменных родительского процесса

Harald ★★★★★
()

передавать не в fork нужно а в exec, после fork все данные, доступные родителю будут доступны и потомку

IvanR ★★★
()

читай что такое форк. если мурзилка стаил то порождается новый процесс с точки вызова форка который наследует страницы и контекст порождающего процесса.

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

и передавать что-либо бессмысленно т.к. порожденный процесс исполняется с точки вызова форка.

exception13 ★★★★★
()

Товарисч, читай маны по fork и exec. Fork — это не запуск программы с ее начала, а расщепление процесса на два, при этом один идет по одной ветке условия «if (pid = fork())», а второй - по другой. При этом можно считать, что копируется весь образ процесса (хотя технически там CoW). А вот exec — это уже замена образа текущей исполняемой программы образом с диска по указанному пути с указанными argv, argc и envp. И в него можно передавать аргументы.

Kiborg ★★★
()

А void, если я правильно понимаю, чаще означает «необязательно» чем «отсутствует».

Нет, не правильно.

В Си func(void) определяет функцию, у которой нет аргументов, а func() — функцию с любым числом аргуметов. В Си++ оба варианта означают, что агрументов нет.

i-rinat ★★★★★
()
Ответ на: комментарий от Harald

Хех, как накинулись-то! )) Отвечая на вопрос «Зачем?» - хотел «быстро» и с минимальными телодвижениями упростить администрирование собственного сервера (для каждого подключившегося вызывается тот самый fork() и в нем идет обработка). По ps -ax можно понять сколько в данный момент времени подключившихся клиентов, но было бы существенно наглядней, если бы у каждого было бы подписано:

pid1 MyProgram parent
pid2 MyProgram user1 ip1 port1
pid3 MyProgram user1 ip2 port2
pid4 MyProgram user2 ip1 port3
pid5 MyProgram user3 ip3 port4
и т.д.

Естественно я не собираюсь эти параметры как-то обрабатывать - мне это действительно не нужно! )))

PS. Варианты с exec тоже читал, но сервер уже написан и функционирует на fork'ах. Переписывать его из-за случайно возникшей блажи - лень, уж скорее вставлю запись в файл пида/логина/ip:port, а в OnExit() - удаление оной строчки с тем, что бы далее парсить один файл понятного формата... PS2. Исходя из стремления к увеличению сугубо наглядности, но помня о природной лени, вариант с файлом, хранящим список онлайн: оптимальный? Или есть еще более «простой» (элегантный) способ??! ))

nk_lg
() автор топика
Ответ на: комментарий от i-rinat

Спасибо, не знал! Знал что

void func()
может вернуть «что угодно», а может и не вернуть, думал в описании параметров работает та же логика... Опасное заблуждение! )

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

может вернуть «что угодно»

Неа, вернуть она может только «ничего».

Когда говорят «что угодно», имеется в виду конкретная реализация. Если, например, в ABI результат функции возвращается в %rax, и при этом ты перепутаешь сигнатуры функций (в одной единице трансляции определишь функцию как void func() {}, а в другой как int func()), то при вызове int var = func() в var действительно может что-то непонятное попасть. Компилятор положит в эту переменную значение регистра %rax.

i-rinat ★★★★★
()
Ответ на: комментарий от nk_lg

Т.е. у вас выполняется fork(), но после нету exec()? Неожиданное решение, в таких случаях обычно используются потоки.

Хак конечно, но что мешает заменить argv[1] собственно?

pid = fork();
if (pid == 0) {
   char info[100]
   sprintf(info, "%s %s %d", user, ip, port);
   strcpy(argv[1], info);
}
# MyProgram "parent                                         " &
# ps ax
...

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

подписано

// gcc -std=c99 q.c -lbsd

#include <sys/types.h>
#include <sys/wait.h>
#include <bsd/unistd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define PROC_CNT 5

int main(int argc, char *argv[], char *envp[]) {
  pid_t c[PROC_CNT];

  setproctitle_init(argc, argv, envp);

  for (int k = 0; k < PROC_CNT; k++) {
    c[k] = fork();
    if (c[k] == 0) {
      setproctitle("forked process with pid=%d", (int)getpid());
      sleep(120);
      exit(0);
    }
  }

  for (int k = 0; k < PROC_CNT; k++)
    wait(NULL);

  printf("done\n");
  return 0;
}
i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

«имеется в виду конкретная реализация» - Ну да, сам, помню, писал такое:

void myFunction()
{
   if (event) return 5;
}
и компилятор компилил. Предупреждение было, но что-то собиралось и даже как-то работало (давно дело было). Тогда и уверился что «так можно», спасибо - разжевали)

«Т.е. у вас выполняется fork(), но после нету exec()? Неожиданное решение, в таких случаях обычно используются потоки.» - Именно, в switch (fork()) вставлен «рабочий цикл». Просто в свое время был взят готовый пример «многопоточного сервера» на просторах, и дописан. А потоки накладывали уйму «усложнений», у меня обработка клиентов «независимая», в потоках пришлось бы расставлять/следить за симафорами при использовании буферов... в общем - лень победила: копи/паст + малость подредактировали и use))

«netstat на вас нет» - Вот честно: я аж с утра проверю/отпишусь... он (netstat) умеет говорить с какого компа/порта какой пользователь прицепился? Учитывая, что клиент на шарпе цепляется (могут несколько разных пользователей с одного компа, может 1 пользователь с разных компов) к «серверной» части на си и «стучится» под логином/паролем, существующими сугубо в рамках этих приложений?? ))

«Хак конечно, но что мешает заменить argv[1] собственно?» - А вот это, по моему, самое то!!! )))))) Спасибо, с утра проверю, если оно: ваще-вааще спасибо!!! ))))

nk_lg
() автор топика
Ответ на: комментарий от i-rinat
setproctitle("MyProgram %s %s %ld", login, ip, port);

- Руки чешутся попробовать, но уже всё повыключал - спать пора, утром проверю... По моему, этот вариант выглядит кошернее чем подмена в argv[], спасибо! ))

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

Можно выделить несколько переменных, а после форка записывать нужные значения в них для каждого подпроцесса. Можно аж целые структуры создавать. В любом случае, логика остается на основании данных род.процесса (копия как никак).

anonymous
()
Ответ на: комментарий от i-rinat

Sorry «долгое» за молчание, продолжаем разговор:

При попытке схалявить:

strcpy(argv[1], "!");
Что характерно - падает, ну и ладно.

setproctitle("MyProgram %s %s %ld", login, ip, port);

таки да, «в чистом виде» под фрю и на убунте не завелось.

В libbsd есть подходящие функции. Почему бы не воспользоваться?

- Идем по ссылке и видим список:

Downstreams
Alpine Linux
ArchLinux
Buildroot
Debian
Fedora
Gentoo
GoboLinux
Mageia
Nutyx
OpenEmbedded
openmamba
openSUSE
OpenWrt
Slackware
Source Mage
Ubuntu
UHU Linux
Yocto Project
Как я уже оговорился: тестирую я всё на убунте, тут вопросов «что брать» не возникает. Сервак же крутится на RedHat'e, скажу честно - я совершенно не спец в данном вопросе, а потому: что из вышеописанного списка нужно скачать(заинклудить?) что бы бинарник потом корректно выполнился и на тесте в убунте и в «боевых условиях» на редхате?

Заранее спасибо! )

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

тестируй на том же RedHat, что на сервере

anonymous
()
Ответ на: комментарий от i-rinat

Разве информации из первой строки исходника не достаточно?

- А-а-а-а!!! )))))) Сори, оно же закаменчено, кто те коменты читает? ШУТКА!!! ))) Каюсь - олень, протупил, спасибо!!! ))))

Не путай void и void*

- Мне бы даже стыдно бы было бы, если бы не было так грустно. При работе с указателями (*) я парюсь всегда. Магия ссылки/разъименования и подобное для меня «за гранью» понимания! Читал... в разное время разных авторов, всё-равно каша в голове. (( Оттого, отчасти, и не стал юзать pthread (там бы 100% пришлось ставить мьютексы-семафоры и кидаться ссылками в функции потоков). В тех редких случаях, когда не получается выкрутиться, дабы работать со значениями я чаще всего ищу решение методом тыка: клепаю наколенку, в которой вывожу printf() все, возможные варианты *point, point, &point, * *point и уже из этого вывода пытаюсь угадать который вариант мне нужно использовать... не всегда удается с первого раза))))

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