pid_t(和类似的类型) - 为什么,为什么?

时间:2011-09-11 14:25:43

标签: c

getpid()之类的调用返回类型为pid_t的值而不是unsigned int的逻辑是什么?还是int?这有什么用?

我猜这与便携性有关?保证pid_t在不同平台上的大小相同,可能有不同大小的int等?

6 个答案:

答案 0 :(得分:39)

我认为恰恰相反:使程序可以跨平台移植,无论例如PID是16位还是32位(甚至更长)。

答案 1 :(得分:31)

原因是允许讨厌的历史实现仍然符合要求。假设您的历史实施(相当常见):

short getpid(void);

当然,现代系统要求pid至少为32位,但如果标准规定:

int getpid(void);

然后使用short的所有历史实现都将变得不符合要求。这被认为是不可接受的,因此创建了pid_t,并且允许实现以pid_t来定义它所喜欢的方式。

请注意,只要您使用足够大的类型来存储任何pid(pid_t例如可以正常工作),您就没有义务在自己的代码中使用intmax_tpid_t 需要存在的唯一原因是标准用于定义getpidwaitpid等。

答案 2 :(得分:9)

在不同的平台和操作系统上,32位计算机上的不同类型(例如pid_t)可能是32位(unsigned int),64位计算机上可能是64位(无符号长整数)。或者,由于某些其他原因,操作系统可能选择具有不同的大小。此外,它在读取代码时明确表示此变量表示“对象”,而不仅仅是任意数字。

答案 3 :(得分:7)

它的目的是使pid_t或任何其他类型的排序与平台无关,这样无论它实际如何实现,它都能正常工作。此实践用于任何需要与平台无关的类型,例如:

  • pid_t:必须足够大才能在您编码的系统上存储PID。据我所知,映射到int,虽然我不熟悉GNU C库。
  • size_tunsigned变量,可以存储sizeof运算符的结果。通常大小与您编码的系统的字大小相等。
  • int16_tintX_t):无论平台如何,都必须是16位,并且不会在不使用2 n 的平台上定义 - 位字节(通常为8位或16位)或者更不频繁地提供从较大类型中精确访问16位的方法(例如,PDP-10的“字节”,可以是任意数量的连续位一个36位字,因此可能正好是16位),因此不支持16位二进制补码整数类型(例如36位系统)。通常映射到现代计算机上的short,尽管它可能是旧版本的int
  • int_least32_tint_leastX_t):必须是可以存储至少32位的最小尺寸,例如36位或72位系统上的36位。通常映射到现代计算机上的int,尽管它可能是旧版本的long
  • int_fastX_t:必须是可以存储至少X位的最快类型。一般来说,如果(X <= word_size)(或char有时为int_fast8_t),则为系统的字大小,如果int_leastX_t则为(X > word_size),则为intmax_t
  • long long:必须是系统支持的最大整数宽度。通常,它在现代系统上至少为64位,尽管某些系统可能支持大于intmax_t的扩展类型(如果是这样,typedef必须是这些类型中最大的类型)。 / LI>
  • 还有更多......

从机制上讲,它允许编译器的安装程序intX_t在幕后标识符(无论是标准类型还是笨拙的内部类型)的适当类型,无论是通过创建适当的头文件,将其编码到编译器的可执行文件或其他一些方法。例如,在32位系统上,Microsoft Visual Studio将实现// 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; 和类似类型,如下所示(注意:我添加的评论):

pid_t

然而,在64位系统上,它们可能不一定以相同的方式实现,并且我可以保证它们不会在古老的16位系统上以相同的方式实现,假设您可以找到一个版本与一个MSVS兼容。

总的来说,无论实现的具体细节如何,它都允许代码正常工作,并且在任何标准兼容系统上满足相同的要求(例如pid_t可以保证足够大以容纳任何有效的PID在所讨论的系统上,无论你编写什么系统)。它还可以防止您不必了解细节,并且必须查找您可能不熟悉的内部名称。简而言之,无论int(或任何其他类似的typedef)是作为shortlong还是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.
}

现在,让我们再试一次:

{{1}}

如果这样使用,它可以帮助您在任何中断之前找到可能存在问题的代码段,并且可以使故障排除比原本更容易。

答案 4 :(得分:2)

程序中的每个进程都有一个特定的进程ID。通过调用pid,我们知道当前进程的已分配ID。当我们使用fork()时,知道pid非常重要,因为它可以接收地返回0!=0个子和父副本的值这两个视频有清晰的解释:video#1 Video#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代表孩子而非zero/greater than zero代表父母。

答案 5 :(得分:0)

有一点需要指出的是,在大多数答案中,我都看到了类似的东西 &#34;使用pid_t使代码在不同的系统上工作&#34; ,这不一定是真的。

我认为准确的措辞应该是:它使代码“编译”#39;在不同的系统上

例如,在使用32位pid_t的系统上编译代码将产生一个二进制文件,如果在另一个使用64位pid_t的系统上运行,可能会中断。