本篇介绍 C语言函数大全-- k 开头的函数
函数声明 | 函数功能 |
---|---|
int kill(pid_t pid, int sig); |
向指定进程或进程组发送一个信号 |
参数:
- pid: 目标进程的 ID(进程ID或进程组ID)
- sig: 要发送的信号编号
#include
#include
#include
#include
void my_handler(int signum)
{
printf("Received signal %d\n", signum);
}
int main()
{
pid_t pid;
int ret;
pid = fork(); // 创建子进程
if (pid == 0) {
// 子进程
printf("Child process started\n");
sleep(10); // 等待父进程发送信号
exit(0);
} else if (pid > 0) {
// 父进程
printf("Parent process started\n");
sleep(5); // 等待子进程创建完毕
ret = kill(pid, SIGINT); // 向子进程发送 SIGINT 信号
if (ret == -1) {
perror("kill failed");
exit(EXIT_FAILURE);
}
printf("Signal sent successfully\n");
wait(NULL); // 等待子进程结束
printf("Child process finished\n");
exit(EXIT_SUCCESS);
} else {
perror("fork failed");
exit(EXIT_FAILURE);
}
return 0;
}
上述示例程序中,我们首先创建一个子进程,并在子进程中等待 10 秒钟。然后,在父进程中发送 SIGINT 信号给子进程,并等待子进程结束。当子进程收到 SIGINT 信号时,会调用 my_handler()
函数来处理信号。
函数声明 | 函数功能 |
---|---|
int kbhit(void); |
在控制台中检测是否有按键被按下 |
如果有按键被按下,该函数返回非零值,否则返回 0。
#include
#include
int main()
{
int ch;
printf("Press any key to continue...\n");
while (!kbhit()) {
// 等待用户按键
}
ch = getch(); // 获取用户按下的键值
printf("You pressed the '%c' key\n", ch);
return 0;
}
函数声明 | 函数功能 |
---|---|
void kprintf(const char *format, ...); |
用于嵌入式系统中输出调试信息 |
注意: 该函数原型和使用方法与标准库中的
printf()
函数类似。不同的是,kprintf()
函数通常需要根据具体的嵌入式系统进行修改,以适应不同的输出方式。
#include
#include
#include
#include
int uart_fd = -1; // 串口文件描述符
void kprintf(const char *format, ...)
{
va_list ap;
char buf[256];
va_start(ap, format);
vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
if (uart_fd != -1) {
write(uart_fd, buf, strlen(buf));
}
}
int init_uart(const char *devname)
{
struct termios tio;
uart_fd = open(devname, O_RDWR | O_NOCTTY);
if (uart_fd == -1) {
perror("open failed");
return -1;
}
memset(&tio, 0, sizeof(tio));
cfmakeraw(&tio);
cfsetspeed(&tio, B115200);
tcsetattr(uart_fd, TCSANOW, &tio);
return 0;
}
int main()
{
int ret;
ret = init_uart("/dev/ttyS0"); // 打开 ttyS0 串口
if (ret == -1) {
exit(EXIT_FAILURE);
}
kprintf("Hello, world!\n"); // 输出调试信息
close(uart_fd); // 关闭串口文件描述符
return 0;
}
上述示例程序中,首先通过 init_uart() 函数打开了 ttyS0 串口,并将其设置为 RAW 模式和波特率 115200。然后,在 main()
函数中调用了 kprintf()
函数来输出一条调试信息。该函数会将调试信息写入 ttyS0 串口中,并发送到外部设备(如 PC)上。
注意:
kprintf()
函数通常需要进行一定的修改以适应具体的嵌入式系统和调试工具,上面仅提供一个简单的示例,不能直接在所有系统中使用。
函数声明 | 函数功能 |
---|---|
void *kmem_cache_alloc(struct kmem_cache *cachep, int flags); |
它是 Linux 内核中的一个函数,用于从指定的内存缓存中分配一个对象 |
参数:
- cachep: 指向所需缓存区的指针
- flags: 用于控制内存分配方式的标志。
#include
#include
#include
#include
struct my_struct {
int a;
char b;
};
static struct kmem_cache *my_cachep;
int my_init(void)
{
struct my_struct *obj;
printk(KERN_INFO "Initializing module...\n");
my_cachep = kmem_cache_create("my_cache", sizeof(struct my_struct), 0, SLAB_HWCACHE_ALIGN, NULL);
if (!my_cachep) {
printk(KERN_ERR "kmem_cache_create failed\n");
return -1;
}
obj = kmem_cache_alloc(my_cachep, GFP_KERNEL);
if (!obj) {
printk(KERN_ERR "kmem_cache_alloc failed\n");
return -1;
}
obj->a = 123;
obj->b = 'A';
printk(KERN_INFO "obj->a = %d, obj->b = '%c'\n", obj->a, obj->b);
return 0;
}
void my_exit(void)
{
printk(KERN_INFO "Exiting module...\n");
kmem_cache_free(my_cachep, obj);
kmem_cache_destroy(my_cachep);
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
上述示例程序中,首先使用 kmem_cache_create()
函数创建了一个名为 my_cache 的内存缓存区,该缓存区能够容纳 struct my_struct
类型的对象。然后,在 my_init()
函数中使用 kmem_cache_alloc()
函数从缓存区中分配了一个 struct my_struct
类型的对象,并进行了初始化操作。最后,在 my_exit()
函数中使用 kmem_cache_free()
函数释放了该对象所占用的内存,然后销毁了整个缓存区。
注意:
kmem_cache_alloc()
函数和其他 Linux 内核函数在用户空间下无法直接使用,通常需要编写内核模块来调用这些函数。
函数声明 | 函数功能 |
---|---|
void kmem_cache_free(struct kmem_cache *cachep, void *objp); |
它是 Linux 内核中的一个函数,用于将之前使用 kmem_cache_alloc() 函数分配的对象释放回内存缓存池,以便下次再次分配使用。 |
参数:
- cachep: 指向之前使用的缓存区的指针
- objp: 要释放的对象的指针。
参考 4.2 所示
注意:
kmem_cache_free()
函数和其他 Linux 内核函数在用户空间下无法直接使用,通常需要编写内核模块来调用这些函数。
函数声明 | 函数功能 |
---|---|
void kmem_cache_destroy(struct kmem_cache *cachep); |
它是 Linux 内核中的一个函数,用于销毁之前使用 kmem_cache_create() 函数创建的内存缓存区。 |
参数:
- cachep: 指向要销毁的缓存区的指针
参考 4.2 所示
注意: 在销毁缓存区之前,必须确保所有从缓存区中分配的内存都已经被释放,否则可能会导致内存泄漏或其他问题。
函数声明 | 函数功能 |
---|---|
void *kmalloc(size_t size, gfp_t flags); |
它是 Linux 内核中的一个函数,用于在内核中分配指定大小的内存空间。 |
参数:
- size: 表示要分配的内存大小
- flags: 表示一组标志位,用于控制内存分配方式。
#include
#include
#include
#include
int my_init(void)
{
void *ptr;
printk(KERN_INFO "Initializing module...\n");
ptr = kmalloc(1024, GFP_KERNEL);
if (!ptr) {
printk(KERN_ERR "kmalloc failed\n");
return -1;
}
/* do something with ptr */
kfree(ptr);
return 0;
}
void my_exit(void)
{
printk(KERN_INFO "Exiting module...\n");
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
上述示例程序中,在 my_init()
函数中我们使用 kmalloc()
函数分配了一个大小为 1024 字节的内存空间,并且对于成功与否进行了检查。然后,在处理完该内存区域之后,使用 kfree()
函数释放了所占用的内存。
注意: 在使用
kmalloc()
函数分配内存时,必须确保所分配的内存不会造成内核堆栈溢出或其他安全问题。另外,由于kmalloc()
函数返回的内存地址可能不是连续的,因此在使用该函数分配大块内存时,需要特别注意内存对齐和分配方式等问题。
函数声明 | 函数功能 |
---|---|
void *kzalloc(size_t size, gfp_t flags); |
它是 Linux 内核中的一个函数,用于分配指定大小的内存空间,并将其初始化为零。 |
参数:
- size: 表示要分配的内存大小
- flags: 表示一组标志位,用于控制内存分配方式。
c
#include
#include
#include
#include
int my_init(void)
{
void *ptr;
printk(KERN_INFO "Initializing module...\n");
ptr = kzalloc(1024, GFP_KERNEL);
if (!ptr) {
printk(KERN_ERR "kzalloc failed\n");
return -1;
}
/* do something with ptr */
kfree(ptr);
return 0;
}
void my_exit(void)
{
printk(KERN_INFO "Exiting module...\n");
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
上述示例程序中,在 my_init()
函数中使用 kzalloc()
函数分配了一个大小为 1024 字节的内存空间,并将其初始化为零。然后,在处理完该内存区域之后,使用 kfree()
函数释放了所占用的内存。
注意: 虽然可以使用
kmalloc()
函数分配内存然后手动初始化为零,但是使用kzalloc()
函数可以更加高效和简单地完成这个操作。另外,由于kzalloc()
函数返回的内存地址是经过清零的,因此在使用该函数分配内存时,无需显式调用memset()
等函数进行初始化操作。
函数声明 | 函数功能 |
---|---|
void kfree(void *ptr); |
它是 Linux 内核中的一个函数,用于释放使用 kmalloc() 或者 kzalloc() 函数分配的内存空间。 |
参数:
- ptr : 指向要释放的内存块的指针。
参考 7.2 所示
注意: 在使用
kfree()
函数释放内存时,必须确保所释放的内存是由kmalloc()
或者kzalloc()
函数分配的,否则可能会导致内核崩溃或其他问题。另外,使用kfree()
函数释放一个指针之后,应该将其设置为NULL
,以避免出现悬挂指针(dangling pointer)等问题。
函数声明 | 函数功能 |
---|---|
void keep(void *ptr); |
它是 Linux 内核中的一个函数,用于防止编译器将指定的符号优化掉。 |
参数:
- ptr: 是指向要保留的符号的指针。
#include
#include
#include
static int my_symbol __attribute__((__used__));
int my_init(void)
{
printk(KERN_INFO "Initializing module...\n");
my_symbol = 123;
/* do something with my_symbol */
keep(&my_symbol); // 保留符号
return 0;
}
void my_exit(void)
{
printk(KERN_INFO "Exiting module...\n");
}
MODULE_LICENSE("GPL");
module_init(my_init);
module_exit(my_exit);
上述示例程序中,在 my_init()
函数中定义了一个整型变量 my_symbol,并且对其进行了初始化。然后,在处理完该变量之后,调用 keep()
函数保留该符号,以避免编译器将其优化掉。
注意: 在使用
keep()
函数时,必须确保所保留的符号不会被优化掉,否则可能会导致程序出错或崩溃。另外,由于keep()
函数只是防止编译器优化符号,并不会改变其可见性或访问权限,因此在使用该函数时,应该确保所保留的符号在需要的位置上是可见和可访问的。