Подтвердить что ты не робот

Почему getpid() возвращает pid_t вместо int?

Какова логика вызовов вроде getpid() возвращающих значение типа pid_t вместо unsigned int? Или int? Как это помогает?

Я предполагаю, что это связано с переносимостью? Гарантия того, что pid_t одинакового размера на разных платформах, которые могут иметь разные размеры int и т.д.?

4b9b3361

Ответ 1

Я думаю, что это наоборот: сделать программу переносимой на разных платформах, независимо от того, является ли PID 16 или 32 битами (или даже больше).

Ответ 2

Причина заключается в том, чтобы позволить неприятным историческим реализациям по-прежнему соответствовать. Предположим, что ваша историческая реализация (довольно распространенная):

short getpid(void);

Конечно, современные системы хотят, чтобы pids были как минимум 32-битными, но если в стандарте указано:

int getpid(void);

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

Обратите внимание, что вы никоим образом не обязаны использовать pid_t в своем собственном коде, если вы используете тип, достаточно большой для хранения любого pid (intmax_t, например, будет работать нормально). Единственная причина, по которой существует pid_t, - это стандартное определение getpid, waitpid и т.д. В терминах этого.

Ответ 3

На разных платформах и операционных системах разные типы (например, pid_t) могут быть 32 бита (unsigned int) на 32-битной машине или 64 бита (без знака) на 64-разрядной машине. Или, по какой-то другой причине, операционная система может выбрать другой размер. Кроме того, это ясно, когда читаете код, что эта переменная представляет собой "объект", а не просто произвольное число.

Ответ 4

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

  • pid_t: должен быть достаточно большим, чтобы хранить PID в системе, для которой вы кодируете. Насколько мне известно, отображается на int, хотя я не очень знаком с библиотекой GNU C.
  • size_t: переменная unsigned способная хранить результат оператора sizeof. Как правило, по размеру соответствует размеру слова системы, для которой вы кодируете.
  • int16_t (intX_t): должно быть ровно 16 бит, независимо от платформы, и не будет определяться на платформах, которые не используют 2 n -bit байтов (обычно 8- или 16 -bit) или, что намного меньше часто предоставляют средства для доступа точно к 16 битам из более крупного типа (например, "байты" PDP-10, которые могут быть любым числом смежных бит из слова 36 -bit и, таким образом, могут быть точно 16 битами ) и, следовательно, не поддерживают 16 -bit двух целочисленных типов дополнения (таких как система 36 -bit). На современных компьютерах, как правило, отображается на short, хотя на старых может использоваться int.
  • int_least32_t (int_leastX_t): должен быть наименьшего возможного размера, который может хранить не менее 32 бит, например, 36 бит в системе 36 -bit или 72 -bit. Обычно отображается на int на современных компьютерах, хотя на старых может быть long.
  • int_fastX_t: должен быть максимально быстрым типом, который может хранить не менее X бит. Обычно это системный размер слова if (X <= word_size) (или иногда char для int_fast8_t), или действует как int_leastX_t if (X > word_size))
  • intmax_t: должна быть максимальной целочисленной шириной, поддерживаемой системой. Как правило, это будет не менее 64 бит в современных системах, хотя некоторые системы могут поддерживать расширенные типы, большие чем long long (и если это так, intmax_t должен быть самым большим из этих типов).
  • И больше...

Механически, это позволяет установщику компилятор typedef во соответствующий тип для идентификатора (будь то стандартного типа или неумело названием внутреннего типа) за кадром, будь то путем создания соответствующих файлов заголовков, кодирование его в компилятор исполняемый файл, или каким - либо другим способом, , Например, в системе 32 -bit Microsoft Visual Studio будет реализовывать intX_t и похожие типы следующим образом (примечание: комментарии, добавленные мной):

// Signed ints of exactly X bits.
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;

// Unsigned ints of exactly X bits.
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

// Signed ints of at least X bits.
typedef signed char int_least8_t;
typedef short int_least16_t;
typedef int int_least32_t;

// Unsigned ints of at least X bits.
typedef unsigned char uint_least8_t;
typedef unsigned short uint_least16_t;
typedef unsigned int uint_least32_t;

// Speed-optimised signed ints of at least X bits.
// Note that int_fast16_t and int_fast32_t are both 32 bits, as a 32-bit processor will generally operate on a full word faster than a half-word.
typedef char int_fast8_t;
typedef int int_fast16_t;
typedef int int_fast32_t;

// Speed-optimised unsigned ints of at least X bits.
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;

typedef _Longlong int64_t;
typedef _ULonglong uint64_t;

typedef _Longlong int_least64_t;
typedef _ULonglong uint_least64_t;

typedef _Longlong int_fast64_t;
typedef _ULonglong uint_fast64_t;

Однако в системе 64 -bit они не обязательно могут быть реализованы одинаково, и я могу гарантировать, что они не будут реализованы одинаково в архаичной системе 16 -bit, при условии, что вы можете найти версию MSVS совместим с одним.

В целом, это позволяет коду работать должным образом независимо от специфики вашей реализации и отвечать тем же требованиям в любой совместимой со стандартами системе (например, pid_t может быть достаточно большим, чтобы содержать любой действительный PID в рассматриваемой системе, нет не имеет значения, для какой системы вы кодируете). Это также препятствует тому, чтобы вы знали о мимолетных мелочах и не искали внутренние имена, с которыми вы, возможно, не знакомы. Короче говоря, он гарантирует, что ваш код работает одинаково независимо от того, pid_t ли pid_t (или любой другой подобный typedef) как int, short, long, long long или даже как __Did_you_really_just_dare_me_to_eat_my_left_shoe__, поэтому вам не нужно,


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

int a, b;

....

if (a > b) {
    // Nothing wrong here, right?  They're both ints.
}

Теперь, давайте попробуем это снова:

size_t a;
pid_t b;

...

if (a > b) {
    // Why are we comparing sizes to PIDs?  We probably messed up somewhere.
}

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

Ответ 5

Каждый процесс в программе имеет определенный идентификатор процесса. Вызывая pid, мы знаем назначенный идентификатор текущего процесса. Знание pid исключительно важно, когда мы используем fork(), потому что он возвращает значения 0 и !=0 для дочерних и родительских копий. Эти два видео имеют четкие объяснения: видео # 1 Видео # 2

Пример: предположим, что у нас есть следующая c-программа:

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


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

  printf("I am %d\n", (int) getpid());
  pid_t pid = fork();
  printf("fork returned: %d\n", (int) pid);
  if(pid<0){
    perror("fork failed");
  }
  if (pid==0){
    printf("This is a child with pid %d\n",(int) getpid());
  }else if(pid >0){
    printf("This is a parent with pid %d\n",(int)getpid());
  }

  return 0;
}

Если вы запустите его, вы получите 0 для child и non zero/greater than zero для родителя.

Ответ 6

Следует отметить одну вещь: в большинстве ответов я видел что-то вроде "использование pid_t заставляет код работать на разных системах", что не всегда верно.

Я считаю, что точная формулировка должна быть такой: она делает код "компилируемым" в разных системах.

Как, например, компиляция кода в системе, которая использует 32-битный pid_t, создаст двоичный файл, который, вероятно, сломается при запуске в другой системе, которая использует 64-битный pid_t.