Какую функцию я могу вызвать из программы C, чтобы узнать, в какой среде z/OS запускается программа, например это z/OS UNIX (он же USS) или это от TSO, скажем, через JCL?
Определение среды, z/OS UNIX по сравнению с JCL или TSO
Ответы (1)
Существует два подхода: CEE3INF и просмотрите области данных z/OS.
Преимущество CEE3INF заключается в том, что он документирован и переносится в любую среду LE, а также предоставляет информацию о PIPI, которую нелегко найти в структурах z/OS.
В качестве альтернативы CEE3INF в области системных данных есть много информации, если вам просто нужно различать пакетную обработку, TSO, CICS и независимо от того, был ли вы дублирован как процесс USS. Альтернатива проста, и она особенно полезна вне среды LE... хотя это легко сделать даже в C, просто загрузив некоторые указатели, которые вы можете получить с помощью утилиты преобразования XLC DSECT в C-структуру.
Адресное пространство TSO — это пространство, в котором ASCBTSB не равно нулю (PSAAOLD->ASCBTSB). Пакетное задание — это задание, в котором указано значение ASCBJBNI (PSAAOLD->ASCBJBNI). В адресном пространстве CICS значение TCBAUF установлено ненулевым (PSATOLD->TCBCAUF).
В любом из вышеперечисленных случаев вы также можете проверить, была ли ваша задача дублирована как процесс UNIX, проверив TCB->STCB->STCBOTCB. Если не ноль, вы дублированы и можете использовать службы UNIX. Поле OTCBPRLI содержит информацию о процессе, такую как PID, а поле THLI содержит информацию об уровне потока.
Обратите внимание, что данная задача может иметь право на использование функций USS, но пока не имеет права. Функция «querydub()» может помочь вам отличить задачу, которая уже дублирована, от задачи, которая может быть дублирована, но еще не дублирована.
Если вы используете CEE3INF, были некоторые комментарии о том, что он не работает должным образом вне функции main(), но я думаю, что проблема заключается в небольшой ошибке в образце, который IBM предоставляет в своей документации. Этот образец отлично работает в моих системах z/OS 2.3 и 2.4:
#include <leawi.h>
#include <string.h>
#include <ceeedcct.h>
int do_call(void)
{
_INT4 sys_subsys,env_info,member_id,gpid;
_FEEDBACK fc;
CEE3INF(&sys_subsys,&env_info,&member_id,&gpid,&fc);
if ( _FBCHECK(fc,CEE000) != 0 )
{
printf("CEE3INF failed with message number %d\n", fc.tok_msgno);
}
printf("System/Subsystem in hex %08x \n",sys_subsys);
printf("Enviornment info in hex %08x \n",env_info);
printf("Member languages in hex %08x \n",member_id);
printf("GPID information in hex %08x \n",gpid);
printf("\n");
}
int main(void)
{
do_call();
}
Это пример кода из руководства IBM, за исключением того, что в вызове CEE3INF указано, что документ IBM содержит ошибку ("...fc" вместо "...&fc"). Были комментарии о том, что CEE3INF не работает, если вызывается вне main(), но я думаю, что проблема просто в ошибке в приведенном выше примере.
Для проверки я скомпилирую приведенный выше код в оболочке UNIX Services с помощью этой команды:
xlc -o testinf testinf.c
Затем я запускаю исполняемый файл из сеанса оболочки z/OS:
> ./testinf
System/Subsystem in hex 02000002
Enviornment info in hex 00540000
Member languages in hex 10000000
GPID information in hex 04020300
Это система z/OS 2.3 - я получаю идентичные результаты на 2.4.
ОБНОВЛЕНИЕ: Что означает «работа в среде z/OS UNIX Services»?
Легко понять, что такое пакетные задания, сеансы TSO и запущенные задачи, но что подразумевается под «выполнением в среде z/OS UNIX Services»? В таких подсистемах, как CICS, IMS или WebSphere, "работа под xxx" легко определить, потому что транзакции выполняются внутри специального типа адресного пространства службы... но, к сожалению, службы UNIX не такие.
В самом деле, почти любая задача, выполняемая в z/OS, может использовать службы z/OS UNIX, поэтому на самом деле не существует «среды служб z/OS UNIX», которую можно было бы определить традиционным способом. Параллельно может быть VSAM ... это программа, которая открывает файл VSAM, «запущенный в VSAM?». Нас могут интересовать программы, работающие с IDCAMS, программы, открывающие файлы VSAM, программы, использующие CICS/VSAM, но «работа в VSAM» не имеет особого смысла без дополнительных уточнений. Кроме того, «запуск в VSAM» не ограничивается запуском в качестве пользователя пакетной обработки, STC или TSO — то же самое и со службами z/OS UNIX — вы можете быть пакетным заданием, запущенной задачей или пользователем TSO, И вы также можете быть "работающим в z/OS UNIX Services" или нет.
Вот три очень разных определения «работы в z/OS UNIX Services»:
- Была ли единица работы «дублирована» как процесс служб UNIX и поэтому готова и способна запрашивать функции ядра служб UNIX.
- Выполняется ли единица работы в оболочке UNIX, такой как /bin/sh.
- Запускается ли программа LE с параметром времени выполнения POSIX(ON).
Почему все это имеет значение? Что ж, некоторые программы, особенно такие, как функции библиотеки времени выполнения, вызываемые другими приложениями, ведут себя по-разному в зависимости от того, является ли вызывающий процесс UNIX-процессом или нет.
Представьте, что вы пишете функцию «OPEN», которая получает в качестве аргумента имя файла. Если ваш вызывающий объект является процессом UNIX, вы можете интерпретировать имя файла как фактическое имя файла... OPEN(XYZ) интерпретируется как "проверить текущий рабочий каталог на наличие файла с именем 'XYZ'". Но если вызывающий объект не дублируется как процесс UNIX, то OPEN(XYZ) может означать открытие оператора DD «XYZ». Вы можете сделать это определение, используя описанный выше подход, поскольку он говорит вам, что ваша задача на самом деле дублируется как процесс UNIX.
Хорошо, но в чем разница между этим и № 2 выше (работает под оболочкой)?
Вот один пример. Предположим, у вас есть вызываемая подпрограмма, которая хочет записать сообщение в выходной файл. Большинство приложений UNIX, отличных от мейнфреймов, будут просто записывать в STDOUT или STDERR, но это не всегда работает в z/OS, потому что многие приложения являются процессами UNIX, но они не работают в оболочке, а без оболочки STDOUT и STDERR может не существовать.
Вот сценарий...
Вы запускаете обычную программу, которая не имеет ничего общего со службами UNIX, но делает что-то, что заставляет ее называться процессом UNIX. Просто в качестве примера, может быть, кто-то помещает "DD PATH=/some/unix/file" в JCL старой программы COBOL... чудесным образом, когда это пакетное задание COBOL запускается, это процесс UNIX, потому что он использует файловая система служб UNIX. Есть много вещей, которые могут привести к тому, что ваша задача будет дублироваться как процесс UNIX ... DD PATH - это один из них, но даже вызов функции, которая открывает сокет TCP / IP, или что-то подобное может помочь. Возможно, вы пишете продукт поставщика, который представляет собой просто программу пакетного ассемблера, но она открывает сокет TCP/IP... это еще один распространенный пример процессов UNIX, которые выполняются без оболочки.
Так почему это проблема? Хорошо, подумайте о том, что произойдет, если эта вызываемая функция решит записать свои сообщения в STDERR. Возможно, он проверяет, работает ли он как процесс служб UNIX, и если да, то он записывает в STDERR, в противном случае он динамически выделяет и записывает в файл SYSOUT. Звучит просто, но это не сработает для моего примера приложения с DD PATH.
Откуда взялся STDERR? Обычно это настраивает программа оболочки UNIX - когда вы запускаете программу в оболочке, оболочка обычно передает вашей программе три предварительно открытых файловых дескриптора для STDIN, STDOUT и STDERR. Поскольку в моем примерном сценарии нет оболочки, эти дескрипторы файлов не были переданы приложению, поэтому запись в STDERR завершится ошибкой. На самом деле, помимо STDIN/STDOUT/STDERR, оболочка передает дочернему процессу множество вещей, таких как переменные среды, обработка сигналов и так далее. (Конечно, пользователь может вручную выделить STDIN/STDOUT/STDERR в своем JCL... Я не говорю об этом здесь).
Если вы хотите иметь программное обеспечение, которое может работать как в оболочке, так и не в оболочке, вам нужно сделать больше, чем просто посмотреть, было ли ваше приложение дублировано как процесс UNIX:
- Проверьте, являетесь ли вы процессом UNIX... если нет, вы не можете работать под оболочкой.
- Проверьте, были ли вы запущены оболочкой. Есть множество способов сделать это, но обычно вы проверяете свой «родительский процесс» или что-то вроде переменных среды, которые вам передали. Это не всегда легко сделать, так как на самом деле в z/OS есть много разных оболочек, так что не так уж много можно найти «законных». Один из наиболее надежных подходов — получить оболочку входа для пользователя и проверить ее.
- В качестве альтернативы проверке родительского процесса вы можете напрямую проверить наличие необходимого вам ресурса, например, вызвав ioctl() для дескриптора файла STDERR, как в моем примере. Это, конечно, может быть опасно... представьте себе случай, когда приложение открывает несколько сокетов и вызывает вашу функцию... то, что вы считаете действительно STDIN/STDOUT/STDERR, на самом деле может быть дескрипторами открытых файлов, настроенными вызывающей стороной, и то, что вы пишете, может легко уничтожить его данные.
Что касается моего третьего примера — программы LE, работающие с POSIX(ON), — это в значительной степени проблема для разработчиков, пишущих на языках высокого уровня на основе среды выполнения LE, поскольку поведение определенных функций среды выполнения отличается от POSIX(ON) или POSIX. (ВЫКЛЮЧЕННЫЙ).
Примером может служить программист на C, пишущий функцию, которая может быть вызвана вызывающими объектами как POSIX(ON), так и POSIX(OFF). Допустим, функция хочет выполнить некоторую фоновую обработку в отдельном потоке... в приложениях POSIX(ON) разработчик может использовать pthread_create(), но это не будет работать в POSIX(OFF). На самом деле в среде выполнения IBM LE есть много вещей, которые ведут себя по-разному в зависимости от настройки POSIX: потоки, обработка сигналов и т. д. и т. д. Если вы надеетесь написать «универсальный» код и вам нужны эти функции, вам обязательно нужно запросить параметр POSIX во время выполнения и использовать разные пути в зависимости от того, как он установлен.
Так что, надеюсь, это проливает свет на сложность, скрывающуюся за этим вопросом... три разных определения «работы в среде z/OS UNIX» и три разных варианта использования, иллюстрирующих, почему каждый из них важен.