Определение среды, z/OS UNIX по сравнению с JCL или TSO

Какую функцию я могу вызвать из программы C, чтобы узнать, в какой среде z/OS запускается программа, например это z/OS UNIX (он же USS) или это от TSO, скажем, через JCL?


person Morag Hughson    schedule 29.03.2020    source источник
comment
Используйте вызываемую службу LE CEE3INF .   -  person cschneid    schedule 29.03.2020
comment
Идеальный! благодарю вас.   -  person Morag Hughson    schedule 30.03.2020
comment
@cschneid Есть ли что-то особенное в CEE3INF, что он не может работать нигде, кроме основной функции в C? Это не работает, если я пытаюсь поместить код в функцию.   -  person Morag Hughson    schedule 30.03.2020
comment
Ничего особенного, о чем я знаю. У меня нет доступа к машине с z/OS, поэтому я не могу сейчас экспериментировать, извините.   -  person cschneid    schedule 30.03.2020
comment
@cschneid, в примечаниях по использованию в документе есть строка, в которой говорится о соображениях z/OS UNIX — CEE3INF разрешен только в потоке, — что кажется неполным предложением, но мне интересно, пытается ли он сказать, только в главный. В любом случае, спасибо за указание на эту функцию. Даже с этим очевидным ограничением это именно то, что мне было нужно. Какой позор, вы не можете написать свой комментарий в качестве ответа!   -  person Morag Hughson    schedule 30.03.2020


Ответы (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»:

  1. Была ли единица работы «дублирована» как процесс служб UNIX и поэтому готова и способна запрашивать функции ядра служб UNIX.
  2. Выполняется ли единица работы в оболочке UNIX, такой как /bin/sh.
  3. Запускается ли программа 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» и три разных варианта использования, иллюстрирующих, почему каждый из них важен.

person Valerie R    schedule 10.04.2020
comment
Если это работает для @MoragHughson, я предлагаю вам объединить два ваших ответа, и (если Мораг согласится) она может принять этот ответ, а я могу удалить свой. - person cschneid; 10.04.2020
comment
Спасибо, что выполнили это! Да, это действительно было так. Я исправил то же самое, и, конечно же, теперь он отлично работает внутри функции. Большое спасибо. Я рад принять ваш ответ, если вы хотите сделать комбинацию, как предлагает @cschneid. - person Morag Hughson; 13.04.2020
comment
Хорошо - объединил два моих ответа и удалил другой ... рад слышать, что это работает для вас. - person Valerie R; 13.04.2020
comment
Привет еще раз! :-) Как вызвать CEE3INF, если я компилирую LP64? В главе KC говорится, что перечисленные вызываемые службы предназначены только для AMODE 31. - person Morag Hughson; 08.05.2020
comment
Я пробовал обход блока управления, о котором вы упомянули, и, к сожалению, в пакетном задании не используется ASCBJBNI (PSAAOLD->ASCBJBNI). При работе в USS у меня также есть имя задания, поэтому это не помогает обнаружить разницу между USS, TSO и Batch. - person Morag Hughson; 08.05.2020
comment
@Morag: USS не зависит от того, является ли единица работы пакетной, STC или TSO ... у вас могут быть пакетные задания, дублированные USS, точно так же, как у вас может быть запущенная задача или пользователь TSO, который использует услуги USS. Процесс USS не является каким-то совершенно другим типом работы в системе — это просто пользователь пакета/STC/TSO, который использует функции UNIX. Если вы думаете об этом как о пакетном задании с использованием служб UNIX или STC, не использующих службы UNIX, а не USS, это какой-то особый тип работы... это распространенное заблуждение. - person Valerie R; 08.05.2020
comment
@Morag: Просто чтобы добавить больше деталей, если вы отправляете пакетное задание, которое просто запускает обычное приложение, оно не пройдет тест USS, описанный выше. С другой стороны, если вы сами напишете короткую программу на C, которая вызывает, скажем, getpid() или открывает сокет TCP/IP или файл файловой системы UNIX, то чудесным образом отправленное вами пакетное задание теперь является процессом UNIX. Вы можете прочитать об этом — это называется дубляж, что в общем означает подключение запущенной задачи к ядру USS. Обычное определение я USS? означает, что я дублирован и могу выполнять вызовы ядра UNIX? - person Valerie R; 08.05.2020
comment
Я не пытаюсь выяснить, является ли мой процесс дублированным процессом USS, я хочу выяснить, работает ли он в среде z/OS UNIX. CEE3INF мог бы мне это сказать. Бит 6 в sys/subsys = в настоящее время выполняется в среде z/OS® UNIX. - person Morag Hughson; 08.05.2020
comment
Любая задача может быть дублирована как процесс UNIX, поэтому вам придется лучше определить, что вы подразумеваете под запуском в среде USS. Я описал способ определить, является ли конкретная задача процессом UNIX. Поскольку в z/OS нет такой вещи, как специальная среда UNIX, ваше определение работы в среде z/OS UNIX может означать работу в оболочке UNIX, вход в систему через SSH или что-то другое, чем единицей работы является процесс UNIX. . Я с удовольствием объясню, как проводить эти тесты, если вы поясните, что вы понимаете под средой z/OS UNIX. - person Valerie R; 08.05.2020
comment
Я не уверен, в чем разница между запуском в оболочке UNIX и входом в систему через SSH, но эти вещи, похоже, соответствуют критериям бита 6 sys/subsys = В настоящее время выполняются в среде z/OS® UNIX, которая CEE3INF сообщили, и именно то, что я после. - person Morag Hughson; 08.05.2020
comment
P.S. Я надеюсь, что это не МОЕ определение работы в среде z/OS UNIX. Я копирую эту фразу прямо из описания CEE3INF KC. - person Morag Hughson; 08.05.2020
comment
Технически любое приложение может быть процессом USS, поэтому многое зависит от того, что вы пытаетесь обнаружить и почему. Ванильная программа COBOL с DD PATH= в JCL технически является процессом UNIX, поскольку она обращается к файловой системе UNIX... это важно для вас? Рассмотрим пользователя TSO, запускающего программу под ISPF ISHELL — все сразу, это процесс UNIX, он запускает оболочку UNIX и это сеанс TSO. CEE3INF вполне может просто протестировать параметр среды выполнения LE POSIX(ON), что является еще одной интерпретацией работы в среде z/OS UNIX. Что проверять, зависит от того, зачем вам это нужно. - person Valerie R; 08.05.2020
comment
Как я уже сказал, я не пытаюсь выяснить, является ли мой процесс дублированным процессом USS, я ищу запуск под оболочкой UNIX. Мои программы будут процессом UNIX, где бы они ни выполнялись. По сути, я хочу воспроизвести то же самое открытие, которое дает мне бит 6 в CEE3INF, поскольку он правильно способен различать запуск в TSO, запуск в пакетном режиме и запуск в z/OS UNIX. Спасибо за ваш расширенный ответ, но вы действительно не сказали, как обнаружить № 2 в вашем списке? Вы упоминаете env vars, но я могу установить env vars в пакетном режиме, так что это тоже не помогает? Как получить оболочку входа? - person Morag Hughson; 10.05.2020
comment
Тестирование показывает, что бит 6 CEE3INF не всегда точен на 100%. Я попробовал простой пример процесса-демона... он запускается оболочкой и имеет такие вещи, как STDOUT/STDERR и переменные среды, но он не проходит описанный вами бит 6. Похоже, что CEE3INF просто получает имя программы оболочки входа пользователя с помощью getpwent(), а затем проверяет имена родительских процессов с помощью getppid() и w_getpsent()... если оболочка входа находится в дереве родительского процесса, вы найдете Это. Является ли это адекватным, зависит от того, почему вы хотите знать, что вы не поделились. - person Valerie R; 11.05.2020