Обмен данными между приложениями с помощью механизма из IPC UNIX System V

Как использовать очереди сообщений, семафоры и разделяемую память, чтобы объединить приложения

Операционная система UNIX® предоставляет большой набор средств для обмена сообщениями между процессами. Механизм Inter-Process Communication (IPC) позволяет использовать эти методы обмена данными для изменения конфигурации приложения во время его выполнения или для совместного использования данных работающими параллельно процессами. В этой статье объясняется, как определить методы, которые приложения могут использовать для взаимодействия, как выбрать наиболее подходящий метод для приложения и начать использовать его.

Шон Волберг, старший сетевой инженер, P.Eng

В академической, корпоративной средах, среде поставщиков интернет-услуг Шон Волберг (Sean Walberg) работает с системами Linux и UNIX с 1994 года. За последнюю пару лет он очень много написал о системном администрировании. Вы можете написать ему на sean@ertw.com.



26.11.2007

Введение

Процессы, которыми управляет ядро UNIX, выполняются автономно, что ведет к более стабильной работе системы. Тем не менее каждый разработчик в конце концов попадает в ситуацию, когда одна группа процессов должна сообщаться с другой группой, например, для обмена данными или передачи команд. Это метод обмена сообщениями называется Inter-Process Communication (IPC). Спецификация System V (SysV) UNIX определяет три механизма для IPC, которые обычно называют SysV IPC:

  • Очереди сообщений
  • Семафоры
  • Совместно используемая память

В дополнение к этому процессы могут взаимодействовать и другими способами, такими как:

  • Чтение, запись и блокировка доступа к файлам
  • Сигналы
  • Сокеты
  • Каналы
  • FIFO (First In, First Out)

Последнюю группу достаточно часто относят к IPC. В этой статье основной акцент делается на IPC-методах SysV ввиду их простоты и эффективности.

Понимание модели SysV

Три IPC-метода SysV имеют сходный синтаксис, несмотря на то, что цели их различны. Обычно следует выполнить следующие действия:

  1. Определите подходящий ключ IPC для использования с ftok(3).
  2. Поставьте IPC-специфичный идентификатор, связанный с ключом IPC, используя для этого msgget(2), semget(2) или shmget(2) для очередей сообщений, семафоров или разделяемой памяти соответственно.
  3. Измените свойства экземпляра IPC при помощи msgctl(2), semctl(2) или shmctl(2).
  4. Используйте конкретный экземпляр IPC.
  5. В конце уничтожьте IPC-экземпляр при помощи msgctl(2), semctl(2) или shmctl(2) и флажка IPC_RMID.

Каждый экземпляр IPC представлен как идентификатор, который помогает отличить его от других экземпляров IPC, существующих в данной системе. Например, каждое из двух разных приложений должно использовать блоки разделяемой памяти, чтобы общесистемный IPC ID смог отличить эти два экземпляра. Возможно, это неочевидно, но основная задача - это понять, каким образом распределять информацию, учитывая то, как привязывать процесс к обычному IPC-экземпляру, и не ставя IPC-механизм на первое место.

Библиотечный вызов ftok использует информацию inode из данного файла и уникальный идентификатор для создания ключа, который не изменяется все время, пока существует файл и идентификатор остается постоянным. Таким образом, два процесса могут использовать свои файлы конфигурации и обрабатываемые в процессе компиляции константы для создания одинакового IPC-ключа. Присутствие констант позволяет одному и тому же приложению с помощью их изменения создавать многочисленные экземпляры IPC-механизма.

Как только у нескольких процессов независимо друг от друга готовы IPC-ключи, они должны получить специальный идентификатор, связанный с определенным IPC-экземпляром посредством системного вызова get. Вызовы get требуют IPC-ключ и набора флажков, равно как и некоторой информации о размере для семафоров и разделяемой памяти. Так как UNIX является многопользовательской системой, среди флажков есть разрешение на доступ к файлу в обычном восьмеричном формате (например, 666 означает, что каждый может читать и записывать файл). Если также поставлен флажок IPC_CREAT, будет создан IPC-экземпляр, если он не существует. Если флажок IPC_CREAT не установлен и IPC-экземпляр не создан, вызов get выдаст сообщение об ошибке.

Существует более простой способ для создания идентификатора IPC-экземпляра для тех приложений, которые могут сделать это самостоятельно. Если для создания IPC вы используете ключ IPC_PRIVATE при вызове get, то идентификатор экземпляра будет уникальным. Для других процессов, которые необходимо подключить к IPC, не требуется вызова get, поскольку у них уже есть идентификатор.

Приложения могут свободно использовать IPC-экземпляры, когда у них есть идентификатор. Каждый IPC-метод отличается от другого и обращение к нему идет только в его разделе.

Передача сообщений через очереди

Очереди сообщений предоставляют механизм, который позволяет одному процессу опубликовать сообщение, которое может получить другой процесс. Когда сообщение получено, оно удаляется из очереди. Очереди сообщений уникальны тем, что оба эти процесса необязательно должны протекать одновременно -- один процесс может опубликовать сообщение и завершиться, а сообщение может быть получено другим процессом несколькими днями позднее.

Сообщения должны состоять из длинного целого, за которыми следует содержимое сообщения. Листинг 1 показывает подобную структуру на C, используя сообщение размером 100 байт.

Листинг 1. С определение образца сообщения
struct mq_message {
    long type;  /* The type or destination */
    char text[100]; /* Data */
};

Получатель сообщения использует тип сообщения. Когда вы получаете сообщение из очереди, вы можете выбрать первое доступное сообщение или можете найти определенный тип сообщений. Типы сообщений для использования являются специфичными для приложений, так как создают очереди, отличающиеся от других форм IPC тем, что ядро распознает передачу данных приложений, читая поле type.

Листинг 2 показывает пример постановки сообщения в очередь.

Листинг 2. Программа, которая ставит сообщения в очередь
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>

int main (void) {

        key_t ipckey;
        int mq_id;
        struct { long type; char text[100]; } mymsg;

        /* Generate the ipc key */
        ipckey = ftok("/tmp/foo", 42);
        printf("My key is %d\n", ipckey);

        /* Set up the message queue */
        mq_id = msgget(ipckey, IPC_CREAT | 0666);
        printf("Message identifier is %d\n", mq_id);

        /* Send a message */
        memset(mymsg.text, 0, 100); /* Clear out the space */
        strcpy(mymsg.text, "Hello, world!");
        mymsg.type = 1;
        msgsnd(mq_id, &mymsg, sizeof(mymsg), 0);

}

Код в листинге 2 импортирует необходимые заголовочные файлы и затем определяет переменные для использования в пределах функции main. Первым делом нужно определить IPC-ключ, используя /tmp/foo как общий файл и число 42 как ID. Для просмотра это число выводится на дисплей с помощью printf(3c). Затем очередь сообщений создается с помощью msgget. Первым параметром для msgget является IPC-ключ, а вторым - набор флажков. В примере флажки имеют восьмеричные разрешения, что позволяет любому, кто имеет IPC-ключ, полностью использовать этот IPC, а также флажок IPC_CREAT, который вызывает msgget для создания очереди. Опять же результат выводится на экран.

Отправлять сообщение в очередь просто. После обнуления пространства памяти в сообщении обычная строка копируется в текстовую часть буфера. Тип сообщения определяется как 1, и затем вызывается msgsnd. msgsnd ожидает передачи ID очереди, указателя на данные, размер данных и флажок, который показывает, должен ли блокироваться вызов или нет. Если выставлен флажок IPC_NOWAIT, вызов возвращается, даже если очередь заполнена. Если же стоит флажок 0, то вызов блокируется до тех пор, пока в очереди не будет свободного места, очередь удаляется либо приложение получает сигнал.

Клиентская часть этого уравнения устроена похожим образом. В листинге 3 приведен пример кода, который извлекает сообщение, отправленное сервером.

Листинг 3. Код для извлечения сообщения из очереди
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>

int main (void) {

        key_t ipckey;
        int mq_id;
        struct { long type; char text[100]; } mymsg;
        int received;

        /* Generate the ipc key */
        ipckey = ftok("/tmp/foo", 42);
        printf("My key is %d\n", ipckey);

        /* Set up the message queue */
        mq_id = msgget(ipckey, 0);
        printf("Message identifier is %d\n", mq_id);

        received = msgrcv(mq_id, &mymsg, sizeof(mymsg), 0, 0);

        printf("%s (%d)\n", mymsg.text, received);
}

Процедура для получения IPC-ключа и идентификатора очереди сообщений аналогична коду сервера. Вызов msgget не определяет никаких флажков, потому что сервер уже создал очередь. Если бы приложения были разработаны так, что клиент мог бы быть запущен раньше сервера, тогда и клиент, и сервер должны были бы определять разрешения на доступ и флажок IPC_CREAT так, чтобы любое приложение, запущенное раньше других, создавало бы очередь.

mq_client.c затем вызывает msgrcv, чтобы получить сообщение из очереди. Первые три переменные определяют идентификатор очереди сообщений, указатель на объем памяти для сообщения и размер буфера. Четвертый параметр - параметр типа, который позволяет вам выбирать то, какие сообщения получать:

  • Если тип 0, то возвращается первое сообщение в очереди.
  • Если тип является положительным целым числом, то возвращается первое сообщение в очереди с таким типом.
  • Если тип является отрицательным целым числом, возвращается первое сообщение в очереди с минимальным значением, которое либо меньше, либо равно абсолютному значению определяемого типа. Например, если 2 и затем 1 были бы добавлены в очередь, вызов msgrcv с типом -2 вернул бы 1, поскольку оно является наименьшим, хотя и стоит вторым в очереди.

Пятым параметром msgrcv опять же является блокирующий флажок. Листинг 4 показывает, как работают клиент и сервер.

Листинг 4. Результаты работы клиентского и серверного кода
sunbox$ ./mq_server
My key is 704654099
Message identifier is 2
sunbox$ ./mq_client
My key is 704654099
Message identifier is 2
Hello, world! (104)

Результаты работы клиента и сервера показывают, что оба они получили одинаковый IPC-ключ, поскольку они ссылались на один и тот же файл и идентификатор. Сервер создал IPC-экземпляр, для которого ядро определило значение 2, а приложение клиента об это узнало. Поэтому не стоит удивляться, что клиент получает "Hello, world!" из очереди сообщений.

Данный пример показывает простейшую из ситуаций. Очередь сообщений может пригодиться для кратковременных процессов, таких как Web-транзакция, которая определяет работу для "тяжелого" приложения back-end, например, как выполнение пакета заданий. Клиент также может быть сервером, и многочисленные приложения могут отправлять сообщения в очередь. Поле типа сообщения позволяет приложениям отправлять сообщения конкретным адресатам.


Блокировка ресурсов с помощью семафоров

Связь между процессами не обязательно должна включать в себя пересылку большого количества данных. На самом деле одного бита может оказаться достаточно, чтобы показать, что процесс использует какой-то определенный ресурс. Рассмотрим два процесса, которым нужен доступ к какому-то аппаратному обеспечению, но только один из которых может использовать его в определенный момент времени. Они могут попеременно использовать счетчик. Если один процесс считывает данные счетчика и видит 1, то понятно, что другой процесс использует аппаратуру. Если значение счетчика равняется 0, то процесс может использовать аппаратуру до тех пор, пока значение счетчика будет установлено как 1 во время выполнения операции и по завершении операции значение будет сброшено до 0.

В данной ситуации существует две проблемы. Первая состоит в настройке общего счетчика и определении того, где он будет находиться, что является наибольшим из неудобств. Вторая проблема состоит в том, что операции запроса и присваивания, необходимые для блокировки ресурсов аппаратуры, не атомарны. Если один процесс должен считал бы значение счетчика как 0, но его опередил бы другой процесс до того, как первый мог бы установить значение счетчика как 1, второй процесс мог бы считывать и присваивать значение счетчика. Оба процесса посчитали бы, что они могут использовать аппаратуру. Нет никакой возможности узнать, присвоил ли значение счетчику другой процесс (процессы). Это называется гонка состояний. Семафоры решают обе эти проблемы, предоставляя общий интерфейс для приложений и используя атомарный тест или операцию присвоения.

В SysV реализация семафоров является более общей, чем описанная выше. Прежде всего, значение семафора не обязательно должно быть 0 или 1; оно может быть 0 или любым положительным числом. Во-вторых, ряд операций с семафорами возможен аналогично параметру type, использованному с msgrcv. Эти операции даются как набор инструментов для ядра, и они либо запускаются все вместе, либо не запускаются вообще. Ядро требует того, чтобы эти команды осуществлялись в структуре, называемой sembuf, которая включает в себя компоненты (в порядке следования):

  1. sem_num: описание того, над каким семафором из набора производится действие.
  2. sem_op: целое число со знаком, содержащее команду или тест, которые должны быть выполнены.
  3. sem_flg: комбинация обычного флажка IPC_NOWAIT, который показывает, нужно ли немедленно запустить тест или блокировать до его завершения, а также SEM_UNDO, которая отменяет операции с семафором в случае преждевременного завершения процесса.

В sem_op имеется большое количество конфигураций:

  • Если sem_op равняется 0, то sem_num тестируется, чтобы посмотреть равно ли значение 0. Если sem_num равняется 0, проводится следующий тест. Если sem_num не равно 0, операция либо блокируется до того момента, как значение семафора будет равно 0 и если IPC_NOWAIT не установлена, либо остальные тесты пропускаются, если установлено IPC_NOWAIT.
  • Если sem_op является положительным целым числом, значение sem_op добавляется к значению семафора.
  • Если sem_op является отрицательным целым числом и отрицательное значение семафора больше или равно абсолютному значению sem_op, то абсолютное значение вычитается из значения семафора.
  • Если sem_op является отрицательным целым числом и значение семафора менее абсолютного значения sem_op, то проведение тестов немедленно останавливается, если IPC_NOWAIT действительно, либо блокируется до того времени, пока значение семафора не станет больше абсолютного значения sem_op.

Пример в листинге 5 разъясняет использование семафоров проверкой программы, которую можно запустить одновременно несколько раз, но гарантирует, что в один момент времени только один процесс будет в критическом разделе. Используется простой вариант семафоров; ресурс свободен, если значение семафора равняется 0.

Листинг 5. Использование семафора для защиты критического раздела
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <string.h> /* For strerror(3c) */
#include <errno.h> /* For errno */
#include <unistd.h> /* rand(3c) */
#include <stdio.h>

int main (int argc, char **argv) {

        key_t ipckey;
        int semid;
        struct sembuf sem[2]; /* sembuf defined in sys/sem.h */

        /* Generate the ipc key */
        ipckey = ftok("/tmp/foo", 42);

        /* Set up the semaphore set. 4 == READ, 2 == ALTER */
        semid = semget(ipckey, 1, 0666 | IPC_CREAT);
        if (semid < 0) {
                printf("Error - %s\n", strerror(errno));
                _exit(1);
        }

        /* These never change so leave them outside the loop */
        sem[0].sem_num = 0;
        sem[1].sem_num = 0;
        sem[0].sem_flg = SEM_UNDO; /* Release semaphore on exit */
        sem[1].sem_flg = SEM_UNDO; /* Release semaphore on exit */
        while(1) { /* loop forever */
                printf("[%s] Waiting for the semaphore to be released\n", argv[1]);
                /* Set up two semaphore operations */
                sem[0].sem_op = 0; /* Wait for zero */
                sem[1].sem_op = 1; /* Add 1 to lock it*/
                semop(semid, sem, 2);
                printf("[%s] I have the semaphore\n", argv[1]);

                sleep(rand() % 3); /* Critical section, sleep for 0-2 seconds */

                sem[0].sem_op = -1; /* Decrement to unlock */
                semop(semid, sem, 1);
                printf("[%s] Released semaphore\n", argv[1]);

                sleep(rand() % 3); /* Sleep 0-2 seconds */
        }

}

Листинг 5 показывает способ так же, как и пример с очередью сообщений. Как msgget определяет размер очереди сообщений во втором параметре, так semget определяет размер набора семафоров. Набор семафоров - это группа семафоров, имеющих общий IPC-экземпляр. Количество семафоров в наборе не может быть изменено. Если был создан набор семафоров, то второй параметр для semget игнорируется. Если semget возвращает отрицательное целое число, говорящее о неудаче, распечатывается причина и осуществляется выход из программы.

Прямо перед основным циклом while инициализируются sem_num и sem_flg, поскольку они остаются постоянными на протяжении всего этого примера. SEM_UNDO определяет, что если владелец семафора выйдет до того, как освобожден семафор, то все другие приложения не будут блокированы.

В этом цикле статусное сообщение печатается для того, чтобы показать, что приложение начало ждать семафор. Это сообщение снабжается первым аргументом командной строки, чтобы отличить его от других экземпляров. Прежде чем войти в критический раздел, приложение блокирует семафор. Прописаны две инструкции семафора. Первая - 0, что означает, что приложение ждет, пока значение семафора не будет сброшено до 0. Вторая - это 1, означающая, что после того, как значение семафора обнулится, к нему добавится 1. Приложение вызывает semop, чтобы запустить команды, передавая их ID семафора, а также адрес структуры данных и количество sembuf команд, которые должны быть использованы.

Когда semop возвращается, приложение узнает, что оно заблокировало семафор и печатает сообщение, чтобы показать это. Затем запускается критический раздел, который в этом случае является паузой на заданное случайно число секунд. В итоге семафор освобождается запуском единой команды sembuf со значением semop равным -1, что имеет эффект вычитания 1 из значения семафора и его обнуления. Распечатывается большее количество отладочного вывода, приложение останавливается на некоторое количество времени, и продолжается выполнение. Листинг 6 показывает вывод двух экземпляров этого приложения.

Листинг 6. Две программы, использующие семафор для защиты критического раздела
sunbox$ ./sem_example a & ./sem_example b &
[a] Waiting for the semaphore to be released
[a] I have the semaphore
[b] Waiting for the semaphore to be released
[a] Released semaphore
[b] I have the semaphore
[a] Waiting for the semaphore to be released
[b] Released semaphore
[a] I have the semaphore
[a] Released semaphore
[a] Waiting for the semaphore to be released
[a] I have the semaphore

Листинг 6 показывает, как запущены два экземпляра под именами a и b соответственно. Сначала a получает семафор, и в это же время b пытается получить блокировку. Как только a освобождает семафор, то b разрешается блокировка. Ситуация обратная в случае, когда a ждет завершения работы b. В итоге a снова присваивает семафор после того, как отключается от него, поскольку b не находится в состоянии ожидания.

Последнее, о чем стоит упомянуть в связи с семафорами, - это то, что они известны как рекомендуемые блокировки. Это означает, что семафоры сами по себе не предотвращают одновременное использование двумя процессами одного ресурса; скорее они нужны для того, чтобы сообщать о том, что ресурсы уже используется.


Общая память

Общая память является, пожалуй, самым мощным IPC-методом SysV и самым простым для выполнения. Как и подразумевает название, блок памяти совместно используется несколькими процессами. Листинг 7 показывает программу, которая вызывает fork(2), чтобы разделиться на порождающий и дочерний процессы, которые сообщаются между собой, используя сегмент общей памяти.

Листинг 7. Программа, иллюстрирующая использование общей памяти
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(void) {

        pid_t pid;
        int *shared; /* pointer to the shm */
        int shmid;

        shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666);
        if (fork() == 0) { /* Child */
                /* Attach to shared memory and print the pointer */
                shared = shmat(shmid, (void *) 0, 0);
                printf("Child pointer  %p\n", shared);
                *shared=1;
                printf("Child value=%d\n", *shared);
                sleep(2);
                printf("Child value=%d\n", *shared);

        } else { /* Parent */
                /* Attach to shared memory and print the pointer */
                shared = shmat(shmid, (void *) 0, 0);
                printf("Parent pointer %p\n", shared);
                printf("Parent value=%d\n", *shared);
                sleep(1);
                *shared=42;
                printf("Parent value=%d\n", *shared);
                sleep(5);
                shmctl(shmid, IPC_RMID, 0);
        }
}

Параметры для shmget должны быть известны к этому времени: ключ, размер и флажки. Размер участка общей памяти в данном примере является одиночным целым числом. Листинг 7 отличается от предыдущих примеров в использовании IPC_PRIVATE для IPC-ключа. Когда используется IPC_PRIVATE, гарантируется уникальный IPC ID, и предполагается, что приложение само представит ID. В примере shmid является и порождающим, и дочерним процессом, поскольку они являются копиями друг друга. Системное обращение fork производит вторую копию текущего процесса, называемого дочерним, которая фактически является идентичной порождающему процессу. Выполнение обоих процессов возобновляется после fork. Результат выполнения fork используется, чтобы определить является ли текущий процесс порождающим или дочерним.

И порождающий процесс, и дочерний выглядят одинаково. Во-первых, системное обращение shmat используется для того, чтобы указатель находился в сегменте общей памяти. shmat требует ID общей памяти, указатель и некоторые флажки. Указатель используется, чтобы запросить определенный адрес памяти. Передавая 0, ядро может выбрать все что угодно. Флажки в основном присущи производителю, тем не менее SHM_RDONLY является общим флажком, который показывает, что сегмент является незаписываемым. Как это показано в листинге 7, shmat часто используется, чтобы разрешить ядру решать все.

shmat возвращает указатель в сегмент общей, который для отладки выдается на экран. Затем каждый процесс изменяет сегмент общей памяти и выводит значение. В итоге порождающий процесс удаляет сегмент общей памяти, используя shmctl(2). Листинг 8 показывает результат выполнения этой программы.

Листинг 8. Пример вывода общей памяти
sunbox$ ./shared_memory
Child pointer  ff390000
Child value=1
Parent pointer ff380000
Parent value=1
Parent value=42
Child value=42

На основе выведенных данных вы можете увидеть совместное использование одного и того же участка общей памяти. Во-первых, значение, которое установил дочерний процесс и прочитал порождающий, в общей памяти равняется 1. Затем порождающий процесс установил значение 42, которое читает дочерний процесс. Заметьте, что у порождающего и дочернего процессов были различные указатели на адреса сегмента общей памяти, хотя доступ они имели к одной и той же физической памяти. Это создает проблему для некоторых структур данных, таких как связанные списки, когда используется физический адрес, так что вы можете использовать соответствующий адрес, если создаете сложные структуры в разделяемой памяти.

Этот пример основывается на том, что один процесс приостановлен, в то время как другой пишет в сегмент разделяемой памяти. В настоящем же приложении это было бы непрактично, поэтому если у вашего приложения несколько процессов осуществляют запись в одну область памяти, продумайте блокировку этой области при помощи семафора.


Заключение

UNIX предоставляет некоторые методы для IPC. IPC-методы SysV - это очереди сообщений, семафоры и общая память. Очереди сообщений позволяют одному приложению отправлять сообщение, которое другие приложения могут получить позднее, даже после завершения работы приложения. Семафоры гарантируют, что разные приложения могут блокировать ресурсы и избегать гонки состояний. Общая память позволяет разным приложениям совместно использовать общий сегмент памяти, что обеспечивает быстрый способ сообщения между ними и передачи большого количества данных. Эти методы можно использовать в сочетании. Например, вы можете использовать семафор, чтобы контролировать доступ к сегменту разделяемой памяти.

IPC-методы полезны для разработчиков приложений, поскольку они предоставляют стандартный способ сообщения между приложения и доступны в разных версиях UNIX. В следующий раз, когда нужно будет заблокировать ресурсы или обеспечить передачу данных между процессами, попробуйте IPC-механизмы SysV.

Ресурсы

Научиться

Получить продукты и технологии

  • Software Distributed Shared Memory: данный проект Университетка Рутгерс развивает концепцию общего пространства памяти на многомашинных комплексах. Цель проекта - использовать стандартное оборудование для распараллелливания заданий вместо компьютера с массово-параллельной архитектурой.(EN)
  • Ознакомительные версии программного обеспечения IBM: программные инструменты для разработки приложений, которые можно бесплатно скачасть с developerWorks.(EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=AIX и UNIX
ArticleID=271213
ArticleTitle=Обмен данными между приложениями с помощью механизма из IPC UNIX System V
publish-date=11262007