Jump to content

კერნელის პროგრამირება C-ში


Recommended Posts

არამგონია კერნელისთვის პროგრამებს/მოდულებს/დრაივერების ბევრი წერდეს აქ (თუ საერთოდ ვინმე წერს) სამწუხაროდ, მაგრამ იყო ეს თემა მაინც. შეიძლება ვინმე დაინტერსდეს და დაიწყოს

 

ინტერნეტშ უამრავი მასალაა, სამწუხაროდ ქართულ ენოვანი სახელმძღვანელო არ მომეპოვება

 

წარმოდგენა რო შეგქმანთ როგორ გამოიყურება კერნელის მოდულები რამდენიმე მაგალითს ქვემოთ დავწერ. გაითვალისწინეთ რომ მარტო უნიქსის სისტემებზე მუშაობს ეს პროგრამები

 

ყვლა კოდს რასაც დავპოსტავ, ჩემი დაწერილია და თუ სადმე გამოიყენებთ არ დაგავიწყდეთ :D

 

დავიწყოთ მარტივით

ეს პროგრამა ბეჭდავს თუ რამდენი პროცესია გშვებული

ps aux ბეჭდავს ყველა პროცესებს, შემდეგ ამას ვამისამერთებთ wc-ში (ასოების, სიტყვების და ხაზბეის თვლა) და შემდეგომ -l -ით ვბეჭდავთ მარტო ხაზებს

// © Otar Bichiashvili 
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int n = system("ps aux | wc -l");
        
    if (n == -1)
        printf ("Errorn");
 
    return 0;
}

ეს ცოტა უფრო დიდი პროგრამაა

წამოდიგინეთ საერთ საპირფარეშო (ტაულეტი) სადაც 3 ადგილია

ქალები და კაცები ერთად რა თქმა უნდა ვერ შევლენ

ტულეტთან დგება რიგი, და შედიან შემდეგი პრინციპით: თუ რიგში კაცია პიველი და ტუალეტი ან ცარიელია, ან კაცია შიგნით და 1 ადგილი მიანცაა თავისუფალი, შედის თუ არადა ელოდება სანამ ადგილი გათვაისფუდლება, ან თუ შიგნით ქალია, მაშინ ელოდება სანამ ყველა გამოვა

იგივე ხდება ქალზეც

// © Otar Bichiashvili

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
 
int manCount,
    womanCount;
    
sem_t x,
      y,
      z,
      womanSem,
      manSem,
      bathroomSize;
 
void Delay(void)
{
    int i;
    int time = random();
    for (i = 0; i < time; i++);
}
 
void *Woman(void *ptr)
{
    sem_wait(&z);
    sem_wait(&womanSem);
    womanCount++;
    
    if (womanCount == 1)
    {
        sem_wait(&manSem); 
    }
    
    sem_post(&y);
    sem_post(&womanSem);
    sem_post(&z);
 
    sem_wait(&bathroomSize);
 
    printf("Woman in!n");
    Delay();
    printf("tWoman out!n");
 
    sem_post(&bathroomSize);     
 
    sem_wait(&y);
    womanCount--;
    
    if (womanCount == 0)
    { 
        sem_post(&manSem); 
    }
    
    sem_post(&y);
}
 
void *Man(void *ptr)
{           
    sem_wait(&z);
    sem_wait(&manSem);
    sem_wait(&x);
    manCount++;
    
    if (manCount == 1)
    { 
        sem_wait(&womanSem); 
    }
    
    sem_post(&x);
    sem_post(&manSem);
    sem_post(&z);
 
    sem_wait(&bathroomSize);
 
    printf("Man in!n");
    Delay();
    printf("tMan out!n");
 
    sem_post(&bathroomSize);
 
    sem_wait(&x);
    manCount--;
    
    if (manCount == 0)
    {
        sem_post(&womanSem);
    }
    
    sem_post(&x);
}
 
int main(void)
{
    int i;
    srandom(60);
 
    manCount = 0;
    womanCount = 0;
    sem_init(&x, 0, 1);  
    sem_init(&y, 0, 1);
    sem_init(&z, 0, 1);
    sem_init(&womanSem, 0, 1);
    sem_init(&manSem, 0, 1);
    sem_init(&bathroomSize, 0, 3); 
 
    pthread_t tid[20];
 
 
    for (i = 0; i < 10; i++)
    {
        pthread_create(&tid, NULL, Woman, NULL);
    }
    
    for (i = 10; i < 20; i++)
    {     
            pthread_create(&tid, NULL, Man, NULL);
    }
    
    for (i = 0; i < 20; i++)
    {     
            pthread_join(tid, NULL);
    }
    
    sem_destroy(&x);
    sem_destroy(&y);
    sem_destroy(&z);
    sem_destroy(&manSem);
    sem_destroy(&womanSem);
    sem_destroy(&bathroomSize);
    
    return 0;
}

შედეგი აპლიკაცია უკვე სრულფასოვანი მოდულია რომელიც შეგიძლიათ დააყენოთ

ეს არის უბრალო დრაივერი რომელიც აკონტროლებს ჩაწერა/წაკითხვას. მარტივად რომ თქვათ სადა დრაივერია რომელიც რეაგირებს ყველა სიმბოლოზე და არ ელოდება რაღაც ბლოკის ზოამს

არსეობობს 2 ტიპის დრაივერები, character (რომელიც ყოველ სიმბოლოს წერს/კითხულობს ცალ-ცალკე) და block (რომელიც სიმბოლობის ჯგუფთან მუშაობს)


// © Otar Bichiashvili

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
 
#include <linux/kernel.h>    /* printk() */
#include <linux/slab.h>        /* kmalloc() */
#include <linux/fs.h>        /* everything... */
#include <linux/errno.h>    /* error codes */
#include <linux/types.h>    /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>    /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
 
#include <asm/system.h>        /* cli(), *_flags */
#include <asm/uaccess.h>    /* copy_*_user */
 
#include "scull.h"        /* local definitions */
 
/*
 * Our parameters which can be set at load time.
 */
 
int scull_major =   SCULL_MAJOR;
int scull_minor =   0;
int scull_nr_devs = SCULL_NR_DEVS;    /* number of bare scull devices */
int scull_quantum = SCULL_QUANTUM;
int scull_qset =    SCULL_QSET;
 
module_param(scull_major, int, S_IRUGO);
module_param(scull_minor, int, S_IRUGO);
module_param(scull_nr_devs, int, S_IRUGO);
module_param(scull_quantum, int, S_IRUGO);
module_param(scull_qset, int, S_IRUGO);
 
MODULE_AUTHOR("A.R.");
MODULE_LICENSE("Dual BSD/GPL");
 
struct scull_dev *scull_devices;    /* allocated in scull_init_module */
 
 
/*
 * Empty out the scull device; must be called with the device
 * semaphore held.
 */
int scull_trim(struct scull_dev *dev)
{
    struct scull_qset *next, *dptr;
    int qset = dev->qset;   /* "dev" is not-null */
    int i;
 
    for (dptr = dev->data; dptr; dptr = next) { /* all the list items */
        if (dptr->data) {
            for (i = 0; i < qset; i++)
                kfree(dptr->data);
            kfree(dptr->data);
            dptr->data = NULL;
        }
        next = dptr->next;
        kfree(dptr);
    }
    dev->size = 0;
    dev->quantum = scull_quantum;
    dev->qset = scull_qset;
    dev->data = NULL;
    return 0;
}
#ifdef SCULL_DEBUG /* use proc only if debugging */
/*
 * The proc filesystem: function to read and entry
 */
 
int scull_read_procmem(char *buf, char **start, off_t offset,
                   int count, int *eof, void *data)
{
    int i, j, len = 0;
    int limit = count - 80; /* Don't print more than this */
 
    for (i = 0; i < scull_nr_devs && len <= limit; i++) {
        struct scull_dev *d = &scull_devices;
        struct scull_qset *qs = d->data;
        if (down_interruptible(&d->sem))
            return -ERESTARTSYS;
        len += sprintf(buf+len,"nDevice %i: qset %i, q %i, sz %lin",
                i, d->qset, d->quantum, d->size);
        for (; qs && len <= limit; qs = qs->next) { /* scan the list */
            len += sprintf(buf + len, "  item at %p, qset at %pn",
                    qs, qs->data);
            if (qs->data && !qs->next) /* dump only the last item */
                for (j = 0; j < d->qset; j++) {
                    if (qs->data[j])
                        len += sprintf(buf + len,
                                "    % 4i: %8pn",
                                j, qs->data[j]);
                }
        }
        up(&scull_devices.sem);
    }
    *eof = 1;
    return len;
}
 
/*
 * Actually create (and remove) the /proc file(s).
 */
 
static void scull_create_proc(void)
{
    struct proc_dir_entry *entry;
    create_proc_read_entry("scullmem", 0 /* default mode */,
            NULL /* parent dir */, scull_read_procmem,
            NULL /* client data */);
    entry = create_proc_entry("scullseq", 0, NULL);
    if (entry)
        entry->proc_fops = &scull_proc_ops;
}
 
static void scull_remove_proc(void)
{
    /* no problem if it was not registered */
    remove_proc_entry("scullmem", NULL /* parent dir */);
    remove_proc_entry("scullseq", NULL);
}
 
 
#endif /* SCULL_DEBUG */
 
 
 
 
 
/*
 * Open and close
 */
 
int scull_open(struct inode *inode, struct file *filp)
{
    struct scull_dev *dev; /* device information */
 
    dev = container_of(inode->i_cdev, struct scull_dev, cdev);
    filp->private_data = dev; /* for other methods */
 
    /* now trim to 0 the length of the device if open was write-only */
    if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {
        if (down_interruptible(&dev->sem))
            return -ERESTARTSYS;
        scull_trim(dev); /* ignore errors */
        up(&dev->sem);
    }
    return 0;          /* success */
}
 
int scull_release(struct inode *inode, struct file *filp)
{
    return 0;
}
/*
 * Follow the list
 */
struct scull_qset *scull_follow(struct scull_dev *dev, int n)
{
    struct scull_qset *qs = dev->data;
 
        /* Allocate first qset explicitly if need be */
    if (! qs) {
        qs = dev->data = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
        if (qs == NULL)
            return NULL;  /* Never mind */
        memset(qs, 0, sizeof(struct scull_qset));
    }
 
    /* Then follow the list */
    while (n--) {
        if (!qs->next) {
            qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
            if (qs->next == NULL)
                return NULL;  /* Never mind */
            memset(qs->next, 0, sizeof(struct scull_qset));
        }
        qs = qs->next;
        continue;
    }
    return qs;
}
 
/*
 * Data management: read and write
 */
 
ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
                loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data; 
    struct scull_qset *dptr;    /* the first listitem */
    int quantum = dev->quantum, qset = dev->qset;
    int itemsize = quantum * qset; /* how many bytes in the listitem */
    int item, s_pos, q_pos, rest;
    ssize_t retval = 0;
 
    if (down_interruptible(&dev->sem))
        return -ERESTARTSYS;
    if (*f_pos >= dev->size)
        goto out;
    if (*f_pos + count > dev->size)
        count = dev->size - *f_pos;
 
    /* find listitem, qset index, and offset in the quantum */
    item = (long)*f_pos / itemsize;
    rest = (long)*f_pos % itemsize;
    s_pos = rest / quantum; q_pos = rest % quantum;
 
    /* follow the list up to the right position (defined elsewhere) */
    dptr = scull_follow(dev, item);
 
    if (dptr == NULL || !dptr->data || ! dptr->data[s_pos])
        goto out; /* don't fill holes */
 
    /* read only up to the end of this quantum */
    if (count > quantum - q_pos)
        count = quantum - q_pos;
 
    if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) {
        retval = -EFAULT;
        goto out;
    }
    *f_pos += count;
    retval = count;
 
  out:
    up(&dev->sem);
    return retval;
}
 
ssize_t scull_write(struct file *filp, const char __user *buf, size_t count,
                loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data;
    struct scull_qset *dptr;
    int quantum = dev->quantum, qset = dev->qset;
    int itemsize = quantum * qset;
    int item, s_pos, q_pos, rest;
    ssize_t retval = -ENOMEM; /* value used in "goto out" statements */
 
    if (down_interruptible(&dev->sem))
        return -ERESTARTSYS;
 
    /* find listitem, qset index and offset in the quantum */
    item = (long)*f_pos / itemsize;
    rest = (long)*f_pos % itemsize;
    s_pos = rest / quantum; q_pos = rest % quantum;
 
    /* follow the list up to the right position */
    dptr = scull_follow(dev, item);
    if (dptr == NULL)
        goto out;
    if (!dptr->data) {
        dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);
        if (!dptr->data)
            goto out;
        memset(dptr->data, 0, qset * sizeof(char *));
    }
    if (!dptr->data[s_pos]) {
        dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
        if (!dptr->data[s_pos])
            goto out;
    }
    /* write only up to the end of this quantum */
    if (count > quantum - q_pos)
        count = quantum - q_pos;
 
    if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) {
        retval = -EFAULT;
        goto out;
    }
    *f_pos += count;
    retval = count;
 
        /* update the size */
    if (dev->size < *f_pos)
        dev->size = *f_pos;
 
  out:
    up(&dev->sem);
    return retval;
}
 
/*
 *  * The "extended" operations -- only seek
 *   */
 
 
loff_t scull_llseek(struct file *filp, loff_t off, int whence)
{
        struct scull_dev *dev = filp->private_data;
        loff_t newpos;
 
        switch(whence)
        {
            case 0: 
                newpos = off;
                break;
            case 1:
                newpos = filp->f_pos + off;
                break;
            case 2:
                newpos = dev->size + off;
                break;
            default:
                return -EINVAL;
        }
 
        if (newpos < 0)
            return -EINVAL;
 
        filp->f_pos = newpos;
 
        return newpos;
}
 
struct file_operations scull_fops = {
    .owner =    THIS_MODULE,
    .read =     scull_read,
    .write =    scull_write,
    .open =     scull_open,
    .release =  scull_release,
};
 
/*
 * Finally, the module stuff
 */
 
/*
 * The cleanup function is used to handle initialization failures as well.
 * Thefore, it must be careful to work correctly even if some of the items
 * have not been initialized
 */
void scull_cleanup_module(void)
{
    int i;
    dev_t devno = MKDEV(scull_major, scull_minor);
 
    /* Get rid of our char dev entries */
    if (scull_devices) {
        for (i = 0; i < scull_nr_devs; i++) {
            scull_trim(scull_devices + i);
            cdev_del(&scull_devices.cdev);
        }
        kfree(scull_devices);
    }
 
#ifdef SCULL_DEBUG /* use proc only if debugging */
    scull_remove_proc();
#endif
 
    /* cleanup_module is never called if registering failed */
    unregister_chrdev_region(devno, scull_nr_devs);
 
}
 
 
/*
 * Set up the char_dev structure for this device.
 */
static void scull_setup_cdev(struct scull_dev *dev, int index)
{
    int err, devno = MKDEV(scull_major, scull_minor + index);
    
    cdev_init(&dev->cdev, &scull_fops);
    dev->cdev.owner = THIS_MODULE;
    dev->cdev.ops = &scull_fops;
    err = cdev_add (&dev->cdev, devno, 1);
    /* Fail gracefully if need be */
    if (err)
        printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}
 
 
int scull_init_module(void)
{
    int result, i;
    dev_t dev = 0;
 
/*
 * Get a range of minor numbers to work with, asking for a dynamic
 * major unless directed otherwise at load time.
 */
    if (scull_major) {
        dev = MKDEV(scull_major, scull_minor);
        result = register_chrdev_region(dev, scull_nr_devs, "scull");
    } else {
        result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
                "scull");
        scull_major = MAJOR(dev);
    }
    if (result < 0) {
        printk(KERN_WARNING "scull: can't get major %dn", scull_major);
        return result;
    }
 
        /* 
     * allocate the devices -- we can't have them static, as the number
     * can be specified at load time
     */
    scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
    if (!scull_devices) {
        result = -ENOMEM;
        goto fail;  /* Make this more graceful */
    }
    memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));
 
        /* Initialize each device. */
    for (i = 0; i < scull_nr_devs; i++) {
        scull_devices.quantum = scull_quantum;
        scull_devices.qset = scull_qset;
        sema_init(&scull_devices.sem, 1);
        scull_setup_cdev(&scull_devices, i);
    }
 
        /* At this point call the init function for any friend device */
    dev = MKDEV(scull_major, scull_minor + scull_nr_devs);
 
#ifdef SCULL_DEBUG /* only when debugging */
    scull_create_proc();
#endif
 
    return 0; /* succeed */
 
  fail:
    scull_cleanup_module();
    return result;
}
 
module_init(scull_init_module);
module_exit(scull_cleanup_module);

რაიმე კითხვები თუ გაქვთ დამისვით და &#036;#^#(|დები გიპასუხოთ

  • Upvote 4
Link to comment
Share on other sites

  • 1 year later...

საინტერესოა. შეგიძლია უცხოური სახელმძღვანელო მირჩიო ამ თემასთან დაკავშირებით?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.