⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 base.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
    fs_info->devfsd_buffer_in_use = TRUE;    next_pos = fs_info->devfsd_buf_in + 1;    if (next_pos >= devfsd_buf_size) next_pos = 0;    entry = (struct devfsd_buf_entry *) fs_info->devfsd_buffer +	fs_info->devfsd_buf_in;    entry->data = data;    entry->type = type;    entry->mode = mode;    entry->uid = uid;    entry->gid = gid;    fs_info->devfsd_buf_in = next_pos;    fs_info->devfsd_buffer_in_use = FALSE;    spin_unlock_irqrestore (&lock, flags);    wake_up_interruptible (&fs_info->devfsd_wait_queue);    return (TRUE);}   /*  End Function devfsd_notify_one  *//** *	devfsd_notify - Notify all devfsd daemons of a change. *	@de: The devfs entry that has changed. *	@type: The type of change event. *	@wait: If TRUE, the functions waits for all daemons to finish processing *		the event. */static void devfsd_notify (struct devfs_entry *de, unsigned int type, int wait){    if (devfsd_notify_one (de, type, de->mode, current->euid,			   current->egid, &fs_info) && wait)	wait_for_devfsd_finished (&fs_info);}   /*  End Function devfsd_notify  *//** *	devfs_register - Register a device entry. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		new name is relative to the root of the devfs. *	@name: The name of the entry. *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*). *	@major: The major number. Not needed for regular files. *	@minor: The minor number. Not needed for regular files. *	@mode: The default file mode. *	@ops: The &file_operations or &block_device_operations structure. *		This must not be externally deallocated. *	@info: An arbitrary pointer which will be written to the @private_data *		field of the &file structure passed to the device driver. You can set *		this to whatever you like, and change it once the file is opened (the next *		file opened will not see this change). * *	Returns a handle which may later be used in a call to devfs_unregister(). *	On failure %NULL is returned. */devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,			       unsigned int flags,			       unsigned int major, unsigned int minor,			       umode_t mode, void *ops, void *info){    int is_new;    struct devfs_entry *de;    if (name == NULL)    {	printk ("%s: devfs_register(): NULL name pointer\n", DEVFS_NAME);	return NULL;    }    if (ops == NULL)    {	if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);	if (ops == NULL)	{	    printk ("%s: devfs_register(%s): NULL ops pointer\n",		    DEVFS_NAME, name);	    return NULL;	}	printk ("%s: devfs_register(%s): NULL ops, got %p from major table\n",		DEVFS_NAME, name, ops);    }    if ( S_ISDIR (mode) )    {	printk("%s: devfs_register(%s): creating directories is not allowed\n",	       DEVFS_NAME, name);	return NULL;    }    if ( S_ISLNK (mode) )    {	printk ("%s: devfs_register(%s): creating symlinks is not allowed\n",		DEVFS_NAME, name);	return NULL;    }    if ( S_ISCHR (mode) && (flags & DEVFS_FL_AUTO_DEVNUM) )    {	if (next_devnum_char >= MAX_DEVNUM)	{	    printk ("%s: devfs_register(%s): exhausted char device numbers\n",		    DEVFS_NAME, name);	    return NULL;	}	major = next_devnum_char >> 8;	minor = next_devnum_char & 0xff;	++next_devnum_char;    }    if ( S_ISBLK (mode) && (flags & DEVFS_FL_AUTO_DEVNUM) )    {	if (next_devnum_block >= MAX_DEVNUM)	{	    printk ("%s: devfs_register(%s): exhausted block device numbers\n",		    DEVFS_NAME, name);	    return NULL;	}	major = next_devnum_block >> 8;	minor = next_devnum_block & 0xff;	++next_devnum_block;    }    de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,			   FALSE);    if (de == NULL)    {	printk ("%s: devfs_register(): could not create entry: \"%s\"\n",		DEVFS_NAME, name);	return NULL;    }#ifdef CONFIG_DEVFS_DEBUG    if (devfs_debug & DEBUG_REGISTER)	printk ("%s: devfs_register(%s): de: %p %s\n",		DEVFS_NAME, name, de, is_new ? "new" : "existing");#endif    if (!is_new)    {	/*  Existing entry  */	if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) &&	     !S_ISREG (de->mode) )	{	    printk ("%s: devfs_register(): existing non-device/file entry: \"%s\"\n",		    DEVFS_NAME, name);	    return NULL;	}	if (de->registered)	{	    printk("%s: devfs_register(): device already registered: \"%s\"\n",		   DEVFS_NAME, name);	    return NULL;	}    }    de->registered = TRUE;    if ( S_ISCHR (mode) || S_ISBLK (mode) )    {	de->u.fcb.u.device.major = major;	de->u.fcb.u.device.minor = minor;    }    else if ( S_ISREG (mode) ) de->u.fcb.u.file.size = 0;    else    {	printk ("%s: devfs_register(): illegal mode: %x\n",		DEVFS_NAME, mode);	return (NULL);    }    de->info = info;    de->mode = mode;    if (flags & DEVFS_FL_CURRENT_OWNER)    {	de->u.fcb.default_uid = current->uid;	de->u.fcb.default_gid = current->gid;    }    else    {	de->u.fcb.default_uid = 0;	de->u.fcb.default_gid = 0;    }    de->registered = TRUE;    de->u.fcb.ops = ops;    de->u.fcb.auto_owner = (flags & DEVFS_FL_AUTO_OWNER) ? TRUE : FALSE;    de->u.fcb.aopen_notify = (flags & DEVFS_FL_AOPEN_NOTIFY) ? TRUE : FALSE;    if (flags & DEVFS_FL_REMOVABLE)    {	de->u.fcb.removable = TRUE;	++de->parent->u.dir.num_removable;    }    de->u.fcb.open = FALSE;    de->show_unreg = ( (boot_options & OPTION_SHOW)			|| (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE;    de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;    de->no_persistence = (flags & DEVFS_FL_NO_PERSISTENCE) ? TRUE : FALSE;    devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);    return de;}   /*  End Function devfs_register  *//** *	unregister - Unregister a device entry. *	@de: The entry to unregister. */static void unregister (struct devfs_entry *de){    struct devfs_entry *child;    if ( (child = de->slave) != NULL )    {	de->slave = NULL;  /* Unhook first in case slave is parent directory */	unregister (child);    }    if (de->registered)    {	devfsd_notify (de, DEVFSD_NOTIFY_UNREGISTERED, 0);	free_dentries (de);    }    de->info = NULL;    if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )    {	de->registered = FALSE;	de->u.fcb.ops = NULL;	return;    }    if ( S_ISLNK (de->mode) )    {	de->registered = FALSE;	if (de->u.symlink.linkname != NULL) kfree (de->u.symlink.linkname);	de->u.symlink.linkname = NULL;	return;    }    if ( S_ISFIFO (de->mode) )    {	de->registered = FALSE;	return;    }    if (!de->registered) return;    if ( !S_ISDIR (de->mode) )    {	printk ("%s: unregister(): unsupported type\n", DEVFS_NAME);	return;    }    de->registered = FALSE;    /*  Now recursively search the subdirectories: this is a stack chomper  */    for (child = de->u.dir.first; child != NULL; child = child->next)    {#ifdef CONFIG_DEVFS_DEBUG	if (devfs_debug & DEBUG_UNREGISTER)	    printk ("%s: unregister(): child->name: \"%s\" child: %p\n",		    DEVFS_NAME, child->name, child);#endif	unregister (child);    }}   /*  End Function unregister  *//** *	devfs_unregister - Unregister a device entry. *	@de: A handle previously created by devfs_register() or returned from *		devfs_find_handle(). If this is %NULL the routine does nothing. */void devfs_unregister (devfs_handle_t de){    if (de == NULL) return;#ifdef CONFIG_DEVFS_DEBUG    if (devfs_debug & DEBUG_UNREGISTER)	printk ("%s: devfs_unregister(): de->name: \"%s\" de: %p\n",		DEVFS_NAME, de->name, de);#endif    unregister (de);}   /*  End Function devfs_unregister  *//** *	devfs_mk_symlink Create a symbolic link in the devfs namespace. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		new name is relative to the root of the devfs. *	@name: The name of the entry. *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*). *	@link: The destination name. *	@handle: The handle to the symlink entry is written here. This may be %NULL. *	@info: An arbitrary pointer which will be associated with the entry. * *	Returns 0 on success, else a negative error code is returned. */int devfs_mk_symlink (devfs_handle_t dir, const char *name, unsigned int flags,		      const char *link, devfs_handle_t *handle, void *info){    int is_new;    unsigned int linklength;    char *newname;    struct devfs_entry *de;    if (handle != NULL) *handle = NULL;    if (name == NULL)    {	printk ("%s: devfs_mk_symlink(): NULL name pointer\n", DEVFS_NAME);	return -EINVAL;    }#ifdef CONFIG_DEVFS_DEBUG    if (devfs_debug & DEBUG_REGISTER)	printk ("%s: devfs_mk_symlink(%s)\n", DEVFS_NAME, name);#endif    if (link == NULL)    {	printk ("%s: devfs_mk_symlink(): NULL link pointer\n", DEVFS_NAME);	return -EINVAL;    }    linklength = strlen (link);    de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,			   FALSE);    if (de == NULL) return -ENOMEM;    if (!S_ISLNK (de->mode) && de->registered)    {	printk ("%s: devfs_mk_symlink(): non-link entry already exists\n",		DEVFS_NAME);	return -EEXIST;    }    if (handle != NULL) *handle = de;    de->mode = S_IFLNK | S_IRUGO | S_IXUGO;    de->info = info;    de->show_unreg = ( (boot_options & OPTION_SHOW)		       || (flags & DEVFS_FL_SHOW_UNREG) ) ? TRUE : FALSE;    de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;    /*  Note there is no need to fiddle the dentry cache if the symlink changes	as the symlink follow method is called every time it's needed  */    if ( de->registered && (linklength == de->u.symlink.length) )    {	/*  New link is same length as old link  */	if (memcmp (link, de->u.symlink.linkname, linklength) == 0) return 0;	return -EEXIST;  /*  Contents would change  */    }    /*  Have to create/update  */    if (de->registered) return -EEXIST;    de->registered = TRUE;    if ( ( newname = kmalloc (linklength + 1, GFP_KERNEL) ) == NULL )    {	struct devfs_entry *parent = de->parent;	if (!is_new) return -ENOMEM;	/*  Have to clean up  */	if (de->prev == NULL) parent->u.dir.first = de->next;	else de->prev->next = de->next;	if (de->next == NULL) parent->u.dir.last = de->prev;	else de->next->prev = de->prev;	kfree (de);	return -ENOMEM;    }    if (de->u.symlink.linkname != NULL) kfree (de->u.symlink.linkname);    de->u.symlink.linkname = newname;    memcpy (de->u.symlink.linkname, link, linklength);    de->u.symlink.linkname[linklength] = '\0';    de->u.symlink.length = linklength;    return 0;}   /*  End Function devfs_mk_symlink  *//** *	devfs_mk_dir - Create a directory in the devfs namespace. *	@dir: The handle to the parent devfs directory entry. If this is %NULL the *		new name is relative to the root of the devfs. *	@name: The name of the entry. *	@info: An arbitrary pointer which will be associated with the entry. * *	Use of this function is optional. The devfs_register() function *	will automatically create intermediate directories as needed. This function *	is provided for efficiency reasons, as it provides a handle to a directory. *	Returns a handle which may later be used in a call to devfs_unregister(). *	On failure %NULL is returned. */devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info){    int is_new;    struct devfs_entry *de;    if (name == NULL)    {	printk ("%s: devfs_mk_dir(): NULL name pointer\n", DEVFS_NAME);	return NULL;    }    de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,			   FALSE);    if (de == NULL)    {	printk ("%s: devfs_mk_dir(): could not create entry: \"%s\"\n",		DEVFS_NAME, name);	return NULL;    }    if (!S_ISDIR (de->mode) && de->registered)    {	printk ("%s: devfs_mk_dir(): existing non-directory entry: \"%s\"\n",		DEVFS_NAME, name);	return NULL;    }#ifdef CONFIG_DEVFS_DEBUG    if (devfs_debug & DEBUG_REGISTER)	printk ("%s: devfs_mk_dir(%s): de: %p %s\n",		DEVFS_NAME, name, de, is_new ? "new" : "existing");#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -