c - 使用 %d 与 %ld 打印 pid,linux

标签 c linux casting printf

我将一系列 pid(即 Linux 进程 ID)存储在一个 long 数组中。我意识到 pid 不是 long,但在使用不同的变量类型方面我别无选择。

当我尝试使用 printf 打印 pid 时,我遇到了这个问题。如果我使用 %ld 打印存储 pidlong,我会得到错误的 pid:

8435315771308 process_ancesto
8358006359962 bash
8353711392665 login
4294967297 init
0 swapper/0

但是,如果我使用 %d 进行打印(这会生成编译器警告),我会得到正确的结果(即通过在终端中键入 ps 返回的结果) :

1969 process_ancesto
1946 bash
1945 login
1 init
0 swapper/0

是什么导致了这种行为? pid -> long 转换是扩大转换,不应引起任何问题。

这是我用来进行返回 pids 的系统调用的程序:

int main(int argc, char *argv[])
{
    struct process_info arr[10];
    long n=0;
    int result = syscall(_CS300_PROCESS_ANCESTORS_, arr,10,&n);
    assert(result==0);
    for(int i=0;i<n;i++) {
        printf("%d %s\n",arr[i].pid,arr[i].name);
    }
    return 0;
}

如果我将 %d 替换为 %ld,它会打印不正确的信息。

这是我记录 pid 的系统调用行:

if(copy_long_to_user(&info_array[num_filled_kernel].pid, &curr_task->pid)) {                
            return -EFAULT;
        }

info_array[num_filled_kernel].pid 是一个 long。

最佳答案

两个问题:

在您的 copy_to_user 中,第二个参数是指向 pid_t 的指针,正如您所说,它是一个 int(32 位).因此,您正在从 32 位变量复制 64 位;如果幸运的话,剩下的 32 位(高半位,因为 x86 是小端字节序)将被内存中接下来的任何内容填充。 (如果你不走运,你会在这里犯错。)当你通过指针访问事物时,不会完成整数转换。

安全地执行此操作的最简单方法是使用临时变量:

long tmp = curr_task->pid; // sign-extension done here
copy_long_to_user(..., &tmp);

然后在您的用户空间代码中,您使用 %d 格式说明符来打印显然是 long 的内容。这行不通; printf 是一个可变参数函数,它不知道其参数应具有的类型,因此无法适本地转换它们。如果您要传递 long,请使用 %ld 格式说明符。

关于c - 使用 %d 与 %ld 打印 pid,linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36658863/

相关文章:

c - 在 C 中的单独文件中包含变量吗?

无法从函数返回 boolean 值

java - ArrayList<>.values.toArray,转换为自定义类型数组

generics - 如何检查该对象是 Haxe 中泛型的实例

linux - 找出符号链接(symbolic link)的位置,Linux?

c - uint16_t uint8_t 还是 size_t?

c - 如何阅读抽象编程信息

c - 为什么 scanf 会用 0 覆盖之前读取的 unsigned char 变量?

linux - Linux 中的调度 : run a task when computer is idle (= no user input)

linux - SVN 1.7.1 问题