(C语言函数大全)

y 开头的函数

1. yperror

1.1 函数说明

函数声明 函数功能
void yperror(char *msg); 在 UNIX 和 Linux 系统中用于将 NISNetwork Information Service)错误代码转换为相应的错误信息

参数:

  • msg : 指向一个字符数组的指针,表示 附加的消息

yperror() 函数打印出与最后一次调用 NIS 服务相关联的错误消息,以及任何作为 msg 参数传递的附加消息。

1.2 演示示例

#include <stdio.h>
#include <rpcsvc/ypclnt.h>

int main()
{
    char *domain = "example.com";
    char *map = "passwd.byname";
    int result;

    result = yp_match(domain, map, "johndoe", 7, &value, &vallen);

    if (result != 0)
    {
        yperror("Error getting NIS information");
        return 1;
    }

    printf("User data: %s\n", value);

    return 0;
}

2. yp_match

2.1 函数说明

函数声明 函数功能
int yp_match(const char *domain, const char *map, const char *key, int keylen, char **val, int *vallen); 在网络信息服务中使用的函数,用于查找 NIS 数据库中的条目

参数:

  • domain : 要查询的NIS域名
  • map : 要查询的映射表名称
  • key : 要查找的键的值
  • keylen : 键值的长度
  • val : 指向一个指针,该指针将被设置为匹配键的值。如果该键未找到,则指针将被设置为NULL
  • vallen: 指向一个整数,它在调用时必须初始化为指定缓冲区大小,返回时包含实际读取的字节数

返回值:

  • 0:成功找到匹配项
  • YPERR_KEY:没有找到指定的键
  • YPERR_DOMAIN:指定的NIS域无法解析
  • YPERR_MAP:指定的映射表不存在
  • YPERR_YPBIND:无法联系ypproc_bind进程
  • YPERR_RPC :RPC故障

2.2 演示示例

详见 1.2 中的演示示例

3. y0【零阶第二类贝塞尔函数】

3.1 函数说明

函数声明 函数功能
double y0(double x); 计算 x 的零阶第二类贝塞尔函数

参数:

  • x : 待计算的值

3.2 演示示例

#include <stdio.h>
#include <math.h>

int main() 
{
    double x = 2.5;
    //  计算 x 的零阶第二类贝塞尔函数
    double result = y0(x); 
    printf("y0(%lf) = %lf\n", x, result);
    return 0;
}

3.3 运行结果

在这里插入图片描述

4. y1【一阶第二类贝塞尔函数】

4.1 函数说明

函数声明 函数功能
double y1(double x); 计算 x 的一阶第二类贝塞尔函数

参数:

  • x : 待计算的值

4.2 演示示例

#include <stdio.h>
#include <math.h>

int main() 
{
    double x = 2.5;
    //  计算 x 的一阶第二类贝塞尔函数
    double result = y1(x); 
    printf("y1(%lf) = %lf\n", x, result);
    return 0;
}

4.3 运行结果

在这里插入图片描述

5. yn【n 阶第二类贝塞尔函数】

5.1 函数说明

函数声明 函数功能
double yn(int n, double x); 计算 xn 阶第二类贝塞尔函数

参数:

  • n : 第二类贝塞尔函数的阶数
  • x : 待计算的值

5.2 演示示例

#include <stdio.h>
#include <math.h>

int main() {
    double x = 1.0;
    int n = 2;
    // 二阶第二类贝塞尔函数
    double value = yn(n, x);
    printf("The value of Y_%d(%.2lf) is: %lf\n", n, x, value);
    return 0;
}

5.3 运行结果

在这里插入图片描述

6. yield_to

6.1 函数说明

函数声明 函数功能
void yield_to(struct task_struct *next); 它是 Linux 内核中的函数,用于将 CPU 控制权从一个进程转移到另一个进程

参数:

  • next : 要切换到的进程的任务结构体指针

6.2 演示示例

#include <linux/sched.h>

asmlinkage void sys_yield(void)
{
    struct task_struct *next, *prev;

    prev = current; // 保存当前进程
    next = list_entry(prev->tasks.next, struct task_struct, tasks); // 获取下一个进程

    yield_to(next); // 切换到下一个进程
}

上述的这个示例程序是一个系统调用,当用户调用 sys_yield() 时,它将获取下一个进程并将控制权传递给它。

注意,在实际的 Linux 内核代码中,yield_to() 函数有更多的参数和复杂的实现细节,因此这个示例仅仅是为了演示其基本思想。

7. yield_to_for

7.1 函数说明

函数声明 函数功能
void yield_to_for(struct task_struct *prev, struct task_struct *next, long timeout); 它是 Linux 内核中的一个函数,用于协作式多任务调度

参数:

  • prev : 指向当前正在运行的任务的 task_struct 结构体
  • next : 指向即将要运行的任务的 task_struct 结构体。
  • timeout : 指示当前任务在放弃 CPU 之前应该等待的时间

yield_to_for() 函数的作用是让当前任务主动让出 CPU,让其他任务有机会运行。

  • 如果 timeout 参数大于零,则当前任务会等待指定的时间后再次运行;
  • 如果 timeout 参数为零,则当前任务会立即重新运行;
  • 如果 timeout 参数小于零,则当前任务不会自动重新运行,直到其他事件发生时再次被唤醒。

7.2 演示示例

#include <linux/sched.h>
#include <linux/time.h>
#include <linux/timer.h>

static int my_tasklet_id;
static struct timer_list my_timer;

void my_tasklet(unsigned long data)
{
    printk("my_tasklet called\n");
}

void my_timer_callback(unsigned long data)
{
    struct task_struct *prev = current;
    struct task_struct *next = &init_task;

    printk("my_timer_callback called\n");

    /* 让当前任务主动让出 CPU */
    yield_to_for(prev, next, 0);

    /* 使用 tasklet 调度后续处理 */
    tasklet_schedule(&my_tasklet);
}

int init_module(void)
{
    printk("module loaded\n");

    /* 注册一个定时器,并在 1 秒后触发回调函数 */
    init_timer(&my_timer);
    my_timer.function = my_timer_callback;
    my_timer.data = 0;
    my_timer.expires = jiffies + HZ;
    add_timer(&my_timer);

    /* 注册一个 tasklet */
    my_tasklet_id = __tasklet_hi_schedule(my_tasklet, 0);

    return 0;
}

void cleanup_module(void)
{
    printk("module unloaded\n");

    /* 删除定时器和 tasklet */
    del_timer_sync(&my_timer);
    tasklet_kill(&my_tasklet);
}

在上述的示例代码中,我们定义了一个定时器和一个 tasklet,定时器的回调函数 my_timer_callback() 中调用了 yield_to_for() 函数,让当前任务主动让出 CPU。当定时器到期时,在内核的调度过程中,会先运行其他可运行的任务,然后再次运行当前任务,并执行 tasklet_schedule,以调度后续处理。

8. yield_to_forced

8.1 函数说明

函数声明 函数功能
void yield_to_forced(struct task_struct *t); 它是 Linux 内核中的一个函数,用于将当前进程放弃 CPU,并强制切换到指定的进程 t 所在的 CPU上执行

参数:

  • t : 待复制的宽字符串

8.2 演示示例

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>

static int __init my_init(void)
{
    struct task_struct *p, *next;

    printk(KERN_INFO "Start of yield_to_forced example.\n");

    // 打印当前进程和它的PID
    printk(KERN_INFO "Current process: %s, PID: %d\n", current->comm, current->pid);

    // 遍历进程列表,寻找一个不是当前进程的进程
    for_each_process(p)
    {
        if (p != current)
        {
            next = p;
            break;
        }
    }

    // 如果找到了,则将当前进程放弃CPU,并强制切换到找到的进程所在的CPU上执行
    if (next)
    {
        yield_to_forced(next);
        printk(KERN_INFO "Switched to process: %s, PID: %d\n", next->comm, next->pid);
    }
    else
    {
        printk(KERN_INFO "No other process found.\n");
    }

    printk(KERN_INFO "End of yield_to_forced example.\n");

    return 0;
}

static void __exit my_exit(void)
{
    printk(KERN_INFO "Module exit.\n");
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("ChatGPT");
MODULE_DESCRIPTION("An example of using yield_to_forced function.");

上述的示例代码中,首先遍历进程列表,找一个不是当前进程的进程;如果找到了,则使用 yield_to_forced() 函数将当前进程放弃 CPU,并强制切换到找到的进程所在的 CPU 上执行。如果找不到这样的进程,则打印一个提示信息。

注意:yield_to_forced() 函数只有在实时进程中才能使用,否则会导致内核崩溃。因此,在使用该函数时一定要小心。

9. yield_to_if_needed

9.1 函数说明

函数声明 函数功能
void yield_to_if_needed(struct task_struct *prev); 将 CPU 资源让给其他需要运行的任务

参数:

  • prev : 当前正在运行的任务结构体的指针

该函数会检查任务 prev 是否需要放弃 CPU 并将控制权交给其他需要运行的任务。如果需要,它将调用 schedule() 函数来选择下一个要运行的任务,并将控制权转移给它。在此过程中,该函数还会执行几个与调度相关的操作,例如检查新选定的任务是否具有更高的优先级,以及将当前任务从 CPU 上下文中删除。

9.2 演示示例

#include <linux/kernel.h>
#include <linux/sched.h>

void my_task_function(void)
{
    while (!kthread_should_stop()) {
        // Do some work here...
        yield_to_if_needed(current);
    }
}

struct task_struct *my_task;

int init_module(void)
{
    my_task = kthread_create(my_task_function, NULL, "my_task");
    if (IS_ERR(my_task)) {
        printk(KERN_ERR "Failed to create my_task\n");
        return PTR_ERR(my_task);
    }

    wake_up_process(my_task);
    return 0;
}

void cleanup_module(void)
{
    kthread_stop(my_task);
}

在上述的示例代码中,

  • 首先,我们创建了一个名为 my_task 的内核线程,并将其添加到运行队列中;
  • 然后,在 my_task_function() 中调用 yield_to_if_needed() 函数,以便在必要时放弃 CPU 控制权;
  • 最后,在模块卸载时,我们停止了 my_task 线程。

10. yield_to_when_done

10.1 函数说明

函数声明 函数功能
void yield_to_when_done(struct task_struct *prev, long state); 它一个 Linux 内核中的函数,它允许当前进程在执行完特定任务时将 CPU 资源让给其他进程,以避免浪费 CPU 时间

参数:

  • prev : 前一个进程的指针
  • state : 进程的状态

10.2 演示示例

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/module.h>

static int my_module_init(void) 
{
    printk(KERN_INFO "Module initialized.\n");

    struct task_struct *prev = current;
    long state = TASK_INTERRUPTIBLE;

    // 执行某些任务

    yield_to_when_done(prev, state);

    return 0;
}

static void my_module_exit(void) 
{
    printk(KERN_INFO "Module exited.\n");
}

module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");

在上述的示例代码中,当模块被加载时,my_module_init() 函数会被调用:

  • 首先,在my_module_init() 函数中,我们打印一条日志;
  • 然后,获取当前进程的指针并将其赋值给 prev 变量;同时,我们将进程的状态设置为可中断状态(TASK_INTERRUPTIBLE);
  • 接着,我们执行某些任务;
  • 随后,调用 yield_to_when_done() 函数,将 CPU 资源让出;
  • 最后,my_module_exit() 函数用于在模块被卸载时清理资源。

参考

  1. [Bessel Function of the Second Kind]