В качестве краткого описания я создаю простое приложение для автоматизации, которое запускает скрипт bash для открытия нового экземпляра. Вы можете сделать это с большинством приложений.
open -n /Applications/Visual\ Studio.app
По завершении сохраняйте приложение-автомат назовите его «VSMac Clone» и назовите его в стиле фанк.
Вы можете использовать тот, который я создал, на свой страх и риск. VSMac Clone
Каждый шаг относительно прост.
В Unix ваш процесс состоит из двух частей - области памяти только для чтения с кодом приложения («текст») и памяти для чтения и записи. area ("данные").
Вилка клонирует область чтения-записи, оставляя текстовую страницу в покое. Теперь у вас есть два процесса, выполняющих один и тот же код. Они отличаются значением регистра - значением, возвращаемым функцией fork, - которое отделяет родительский элемент от дочернего.
Exec заменяет текстовую страницу, оставляя страницу данных в покое. Есть много форм exec, в зависимости от того, сколько информации о среде вы ему передаете. См. http://linux.die.net/man/3/exec для получения дополнительного списка вариантов.
Причина двухэтапного режима - гибкость. Между этими двумя шагами вы можете изменить контекст дочернего процесса, который унаследует вновь запущенная программа.
Некоторые вещи, которые вы можете захотеть изменить:
Если вы не разделили fork и exec и вместо этого имели одно порождение - как и системный вызов, ему нужно будет принимать аргументы для каждого из этих атрибутов процесса, если вы хотите, чтобы они устанавливались по-разному в дочернем процессе. Например, см. Список аргументов для CreateProcess в Windows API.
С помощью fork / exec вы изменяете любые наследуемые атрибуты процесса, которые хотите, в дочернем процессе, прежде чем запускать новую программу.
Настройка файловых дескрипторов - одна из наиболее распространенных вещей, которые нужно изменить в контексте дочернего процесса. Если вы хотите захватить вывод программы, вы обычно создаете конвейер в родительском процессе с помощью системного вызова pipe (2), а после fork (2) ing вы закроете конец записи в родительском процессе и закроете read end в дочернем процессе перед вызовом execve (2). (Вы также будете использовать dup (2), чтобы установить дочерний конец канала как файловый дескриптор 1 (stdout)). Это либо невозможно, либо ограничивает один системный вызов.
вы закроете конец записи в родительском процессе и закроете конец чтения в дочернем процессе перед вызовом execve (2). (Вы также будете использовать dup (2), чтобы установить дочерний конец канала как файловый дескриптор 1 (stdout)). Это либо невозможно, либо ограничивает один системный вызов. вы закроете конец записи в родительском процессе и закроете конец чтения в дочернем процессе перед вызовом execve (2). (Вы также будете использовать dup (2), чтобы установить дочерний конец канала как файловый дескриптор 1 (stdout)). Это либо невозможно, либо ограничивает один системный вызов.Есть много других вариантов exec:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
Семейство функций "exec" заменяет текущий образ процесса (откуда он вызывается) новым образом процесса, поэтому вызывающий образ заменяется новым образом процесса. Например, если бы вы запускали команду ls из оболочки (/ bin / sh или / bin / csh), тогда оболочка ответила бы на новый процесс, который затем выполнил бы ls. Как только команда ls завершает работу, она возвращает управление родительскому процессу, которым в этом примере является оболочка.
Если бы не было функциональности вилки, оболочка была бы заменена процессом ls, который после выхода оставил бы вам недоступный терминал, так как образ оболочки в памяти был заменен при вызове exec к ls.
Варианты семейства 'exec' смотрите в ответе 0x6adb015.